1 #include <linux/kernel.h>
2 #include <linux/delay.h>
3 #include <linux/interrupt.h>
6 #define HDMI_MAX_TRY_TIMES 1
9 static char *envp[] = {"INTERFACE=HDMI", NULL};
11 static void hdmi_sys_show_state(struct hdmi *hdmi)
16 hdmi_dbg(hdmi->dev, "HDMI_SLEEP\n");
19 hdmi_dbg(hdmi->dev, "HDMI_INITIAL\n");
22 hdmi_dbg(hdmi->dev, "WAIT_HOTPLUG\n");
25 hdmi_dbg(hdmi->dev, "READ_PARSE_EDID\n");
27 case WAIT_HDMI_ENABLE:
28 hdmi_dbg(hdmi->dev, "WAIT_HDMI_ENABLE\n");
31 hdmi_dbg(hdmi->dev, "SYSTEM_CONFIG\n");
34 hdmi_dbg(hdmi->dev, "CONFIG_VIDEO\n");
37 hdmi_dbg(hdmi->dev, "CONFIG_AUDIO\n");
40 hdmi_dbg(hdmi->dev, "PLAY_BACK\n");
43 hdmi_dbg(hdmi->dev, "Unkown State %d\n", state);
48 int hdmi_sys_init(struct hdmi *hdmi)
50 hdmi->hotplug = HDMI_HPD_REMOVED;
51 hdmi->state = HDMI_SLEEP;
52 hdmi->enable = HDMI_ENABLE;
53 hdmi->autoconfig = HDMI_AUTO_CONFIGURE;
54 hdmi->display = HDMI_DISABLE;
56 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
57 hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
58 hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
59 hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORD_LENGTH;
61 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
62 INIT_LIST_HEAD(&hdmi->edid.modelist);
66 void hdmi_sys_remove(struct hdmi *hdmi)
70 audio_need = hdmi->edid.base_audio_support == 1 && hdmi->edid.sink_hdmi == 1;
72 fb_destroy_modelist(&hdmi->edid.modelist);
74 kfree(hdmi->edid.audio);
77 if(hdmi->edid.specs->modedb)
78 kfree(hdmi->edid.specs->modedb);
79 kfree(hdmi->edid.specs);
81 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
82 INIT_LIST_HEAD(&hdmi->edid.modelist);
83 hdmi->display = HDMI_DISABLE;
85 hdmi->set_vif(hdmi,hdmi->lcdc->screen1,0);
86 rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id);
87 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
91 switch_set_state(&(hdmi->switch_hdmi), 0);
95 static void hdmi_sys_sleep(struct hdmi *hdmi)
97 mutex_lock(&hdmi->enable_mutex);
98 if(hdmi->enable && hdmi->irq)
99 disable_irq(hdmi->irq);
100 hdmi->state = HDMI_SLEEP;
102 if(hdmi->enable && hdmi->irq)
103 enable_irq(hdmi->irq);
104 mutex_unlock(&hdmi->enable_mutex);
107 static int hdmi_process_command(struct hdmi *hdmi)
109 int change, state = hdmi->state;
111 change = hdmi->command;
112 if(change != HDMI_CONFIG_NONE)
114 hdmi->command = HDMI_CONFIG_NONE;
117 case HDMI_CONFIG_ENABLE:
119 mutex_lock(&hdmi->enable_mutex);
120 if(!hdmi->enable || hdmi->suspend)
122 if(hdmi->hotplug == HDMI_HPD_ACTIVED)
123 hdmi_sys_remove(hdmi);
124 hdmi->state = HDMI_SLEEP;
125 hdmi->hotplug = HDMI_HPD_REMOVED;
129 mutex_unlock(&hdmi->enable_mutex);
130 if(hdmi->wait == 1) {
131 complete(&hdmi->complete);
135 case HDMI_CONFIG_COLOR:
136 if(state > CONFIG_VIDEO)
137 state = CONFIG_VIDEO;
139 case HDMI_CONFIG_HDCP:
141 case HDMI_CONFIG_DISPLAY:
143 case HDMI_CONFIG_AUDIO:
144 if(state > CONFIG_AUDIO)
145 state = CONFIG_AUDIO;
147 case HDMI_CONFIG_VIDEO:
149 if(state > SYSTEM_CONFIG)
150 state = SYSTEM_CONFIG;
153 if(hdmi->wait == 1) {
154 complete(&hdmi->complete);
161 else if(state == HDMI_SLEEP)
162 state = WAIT_HOTPLUG;
166 static DEFINE_MUTEX(work_mutex);
168 void hdmi_work(struct work_struct *work)
170 int hotplug, state_last;
171 int rc = HDMI_ERROR_SUCESS, trytimes = 0;
172 struct hdmi_video_para video;
173 struct delayed_work *delay_work = container_of(work, struct delayed_work, work);
174 struct hdmi *hdmi = container_of(delay_work, struct hdmi, delay_work);
176 mutex_lock(&work_mutex);
177 /* Process hdmi command */
178 hdmi->state = hdmi_process_command(hdmi);
180 if(!hdmi->enable || hdmi->suspend) {
181 mutex_unlock(&work_mutex);
184 hotplug = hdmi->detect_hotplug(hdmi);
185 hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __FUNCTION__, hotplug, hdmi->hotplug);
187 if(hotplug != hdmi->hotplug)
189 if(hotplug == HDMI_HPD_ACTIVED){
192 hdmi->state = READ_PARSE_EDID;
194 else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
195 hdmi_sys_remove(hdmi);
196 hdmi->hotplug = hotplug;
197 if(hotplug == HDMI_HPD_REMOVED)
198 hdmi_sys_sleep(hdmi);
200 hdmi->state = WAIT_HOTPLUG;
203 if(hdmi->wait == 1) {
204 complete(&hdmi->complete);
207 mutex_unlock(&work_mutex);
210 else if(hotplug == HDMI_HPD_REMOVED) {
211 hdmi->state = HDMI_SLEEP;
214 hdmi->hotplug = hotplug;
216 else if(hotplug == HDMI_HPD_REMOVED)
217 hdmi_sys_sleep(hdmi);
220 hdmi_sys_show_state(hdmi);
221 state_last = hdmi->state;
224 case READ_PARSE_EDID:
225 rc = hdmi_sys_parse_edid(hdmi);
226 if(rc == HDMI_ERROR_SUCESS)
228 hdmi->state = SYSTEM_CONFIG;
229 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD, envp);
230 hdmi_dbg(hdmi->dev,"[%s] base_audio_support =%d,sink_hdmi = %d\n", __FUNCTION__, hdmi->edid.base_audio_support, hdmi->edid.sink_hdmi);
232 if(hdmi->edid.base_audio_support == 1 && hdmi->edid.sink_hdmi == 1)
233 switch_set_state(&(hdmi->switch_hdmi), 1);
238 #ifdef CONFIG_HDMI_RK616
242 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
244 hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
245 rc = hdmi_switch_fb(hdmi, hdmi->vic);
246 if(rc == HDMI_ERROR_SUCESS)
247 hdmi->state = CONFIG_VIDEO;
250 hdmi->display = HDMI_DISABLE;
251 video.vic = hdmi->vic;
252 video.input_mode = VIDEO_INPUT_RGB_YCBCR_444;
253 video.input_color = VIDEO_INPUT_COLOR_RGB;//VIDEO_INPUT_COLOR_YCBCR
254 video.output_mode = hdmi->edid.sink_hdmi;
256 if(hdmi->edid.ycbcr444)
257 video.output_color = VIDEO_OUTPUT_YCBCR444;
258 else if(hdmi->edid.ycbcr422)
259 video.output_color = VIDEO_OUTPUT_YCBCR422;
261 video.output_color = VIDEO_OUTPUT_RGB444;
262 // For DVI, output RGB
263 if(hdmi->edid.sink_hdmi == 0)
264 video.output_color = VIDEO_OUTPUT_RGB444;
266 rc = hdmi->config_video(hdmi, &video);
267 if(rc == HDMI_ERROR_SUCESS)
269 if(hdmi->edid.sink_hdmi)
270 hdmi->state = CONFIG_AUDIO;
272 hdmi->state = PLAY_BACK;
276 rc = hdmi->config_audio(hdmi, &(hdmi->audio));
278 if(rc == HDMI_ERROR_SUCESS)
279 hdmi->state = PLAY_BACK;
282 if(hdmi->display != HDMI_ENABLE) {
283 hdmi->control_output(hdmi, HDMI_ENABLE);
284 hdmi->display = HDMI_ENABLE;
290 if(hdmi->wait == 1) {
291 complete(&hdmi->complete);
298 if(rc != HDMI_ERROR_SUCESS)
303 if(hdmi->state != state_last)
306 }while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
308 hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
309 mutex_unlock(&work_mutex);