1 #include <linux/kernel.h>
2 #include <linux/delay.h>
5 #ifdef CONFIG_RK_HDMI_CTL_CODEC
6 extern void codec_set_spk(bool on);
9 #define HDMI_MAX_TRY_TIMES 1
12 static char *envp[] = {"INTERFACE=HDMI", NULL};
14 static void hdmi_sys_show_state(int state)
19 hdmi_dbg(hdmi->dev, "HDMI_SLEEP\n");
22 hdmi_dbg(hdmi->dev, "HDMI_INITIAL\n");
25 hdmi_dbg(hdmi->dev, "WAIT_HOTPLUG\n");
28 hdmi_dbg(hdmi->dev, "READ_PARSE_EDID\n");
30 case WAIT_HDMI_ENABLE:
31 hdmi_dbg(hdmi->dev, "WAIT_HDMI_ENABLE\n");
34 hdmi_dbg(hdmi->dev, "SYSTEM_CONFIG\n");
37 hdmi_dbg(hdmi->dev, "CONFIG_VIDEO\n");
40 hdmi_dbg(hdmi->dev, "CONFIG_AUDIO\n");
43 hdmi_dbg(hdmi->dev, "PLAY_BACK\n");
46 hdmi_dbg(hdmi->dev, "Unkown State %d\n", state);
51 int hdmi_sys_init(void)
53 hdmi->hotplug = HDMI_HPD_REMOVED;
54 hdmi->state = HDMI_SLEEP;
55 hdmi->enable = HDMI_ENABLE;
56 hdmi->autoconfig = HDMI_AUTO_CONFIGURE;
57 hdmi->display = HDMI_DISABLE;
59 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
60 hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
61 hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
62 hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORD_LENGTH;
64 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
65 INIT_LIST_HEAD(&hdmi->edid.modelist);
69 void hdmi_sys_remove(void)
71 fb_destroy_modelist(&hdmi->edid.modelist);
73 kfree(hdmi->edid.audio);
76 if(hdmi->edid.specs->modedb)
77 kfree(hdmi->edid.specs->modedb);
78 kfree(hdmi->edid.specs);
80 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
81 INIT_LIST_HEAD(&hdmi->edid.modelist);
82 hdmi->display = HDMI_DISABLE;
84 hdmi->set_vif(hdmi->lcdc->screen1,0);
85 rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id);
86 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
88 switch_set_state(&(hdmi->switch_hdmi), 0);
90 #ifdef CONFIG_RK_HDMI_CTL_CODEC
95 static void hdmi_sys_sleep(void)
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(void)
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)
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;
174 mutex_lock(&work_mutex);
175 /* Process hdmi command */
176 hdmi->state = hdmi_process_command();
178 if(!hdmi->enable || hdmi->suspend) {
179 mutex_unlock(&work_mutex);
182 hotplug = hdmi->detect_hotplug();
183 hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __FUNCTION__, hotplug, hdmi->hotplug);
185 if(hotplug != hdmi->hotplug)
187 if(hotplug == HDMI_HPD_ACTIVED){
190 hdmi->state = READ_PARSE_EDID;
192 else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
194 hdmi->hotplug = hotplug;
195 if(hotplug == HDMI_HPD_REMOVED)
198 hdmi->state = WAIT_HOTPLUG;
201 if(hdmi->wait == 1) {
202 complete(&hdmi->complete);
205 mutex_unlock(&work_mutex);
208 else if(hotplug == HDMI_HPD_REMOVED) {
209 hdmi->state = HDMI_SLEEP;
212 hdmi->hotplug = hotplug;
214 else if(hotplug == HDMI_HPD_REMOVED)
218 hdmi_sys_show_state(hdmi->state);
219 state_last = hdmi->state;
222 case READ_PARSE_EDID:
223 rc = hdmi_sys_parse_edid(hdmi);
224 if(rc == HDMI_ERROR_SUCESS)
226 hdmi->state = SYSTEM_CONFIG;
227 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD, envp);
229 switch_set_state(&(hdmi->switch_hdmi), 1);
231 #ifdef CONFIG_RK_HDMI_CTL_CODEC
238 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
240 hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
241 rc = hdmi_switch_fb(hdmi, hdmi->vic);
242 if(rc == HDMI_ERROR_SUCESS)
243 hdmi->state = CONFIG_VIDEO;
246 hdmi->display = HDMI_DISABLE;
247 video.vic = hdmi->vic;
248 video.input_mode = VIDEO_INPUT_RGB_YCBCR_444;
249 video.input_color = VIDEO_INPUT_COLOR_RGB;//VIDEO_INPUT_COLOR_YCBCR
250 video.output_mode = hdmi->edid.sink_hdmi;
252 if(hdmi->edid.ycbcr444)
253 video.output_color = VIDEO_OUTPUT_YCBCR444;
254 else if(hdmi->edid.ycbcr422)
255 video.output_color = VIDEO_OUTPUT_YCBCR422;
257 video.output_color = VIDEO_OUTPUT_RGB444;
258 // For DVI, output RGB
259 if(hdmi->edid.sink_hdmi == 0)
260 video.output_color = VIDEO_OUTPUT_RGB444;
262 rc = hdmi->config_video(&video);
263 if(rc == HDMI_ERROR_SUCESS)
265 if(hdmi->edid.sink_hdmi)
266 hdmi->state = CONFIG_AUDIO;
268 hdmi->state = PLAY_BACK;
272 rc = hdmi->config_audio(&(hdmi->audio));
274 if(rc == HDMI_ERROR_SUCESS)
275 hdmi->state = PLAY_BACK;
278 if(hdmi->display != HDMI_ENABLE) {
279 hdmi->control_output(HDMI_ENABLE);
280 hdmi->display = HDMI_ENABLE;
286 if(hdmi->wait == 1) {
287 complete(&hdmi->complete);
294 if(rc != HDMI_ERROR_SUCESS)
299 if(hdmi->state != state_last)
302 }while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
304 hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
305 mutex_unlock(&work_mutex);