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;
83 rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id);
84 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
86 switch_set_state(&(hdmi->switch_hdmi), 0);
88 #ifdef CONFIG_RK_HDMI_CTL_CODEC
93 static void hdmi_sys_sleep(void)
95 mutex_lock(&hdmi->enable_mutex);
96 if(hdmi->enable && hdmi->irq)
97 disable_irq(hdmi->irq);
98 hdmi->state = HDMI_SLEEP;
100 if(hdmi->enable && hdmi->irq)
101 enable_irq(hdmi->irq);
102 mutex_unlock(&hdmi->enable_mutex);
105 static int hdmi_process_command(void)
107 int change, state = hdmi->state;
109 change = hdmi->command;
110 if(change != HDMI_CONFIG_NONE)
112 hdmi->command = HDMI_CONFIG_NONE;
115 case HDMI_CONFIG_ENABLE:
117 mutex_lock(&hdmi->enable_mutex);
118 if(!hdmi->enable || hdmi->suspend)
120 if(hdmi->hotplug == HDMI_HPD_ACTIVED)
122 hdmi->state = HDMI_SLEEP;
123 hdmi->hotplug = HDMI_HPD_REMOVED;
127 mutex_unlock(&hdmi->enable_mutex);
128 if(hdmi->wait == 1) {
129 complete(&hdmi->complete);
133 case HDMI_CONFIG_COLOR:
134 if(state > CONFIG_VIDEO)
135 state = CONFIG_VIDEO;
137 case HDMI_CONFIG_HDCP:
139 case HDMI_CONFIG_DISPLAY:
141 case HDMI_CONFIG_AUDIO:
142 if(state > CONFIG_AUDIO)
143 state = CONFIG_AUDIO;
145 case HDMI_CONFIG_VIDEO:
147 if(state > SYSTEM_CONFIG)
148 state = SYSTEM_CONFIG;
151 if(hdmi->wait == 1) {
152 complete(&hdmi->complete);
159 else if(state == HDMI_SLEEP)
160 state = WAIT_HOTPLUG;
164 static DEFINE_MUTEX(work_mutex);
166 void hdmi_work(struct work_struct *work)
168 int hotplug, state_last;
169 int rc = HDMI_ERROR_SUCESS, trytimes = 0;
170 struct hdmi_video_para video;
172 mutex_lock(&work_mutex);
173 /* Process hdmi command */
174 hdmi->state = hdmi_process_command();
176 if(!hdmi->enable || hdmi->suspend) {
177 mutex_unlock(&work_mutex);
180 hotplug = hdmi->detect_hotplug();
181 hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __FUNCTION__, hotplug, hdmi->hotplug);
183 if(hotplug != hdmi->hotplug)
185 if(hotplug == HDMI_HPD_ACTIVED){
188 hdmi->state = READ_PARSE_EDID;
190 else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
192 hdmi->hotplug = hotplug;
193 if(hotplug == HDMI_HPD_REMOVED)
196 hdmi->state = WAIT_HOTPLUG;
199 if(hdmi->wait == 1) {
200 complete(&hdmi->complete);
203 mutex_unlock(&work_mutex);
206 else if(hotplug == HDMI_HPD_REMOVED) {
207 hdmi->state = HDMI_SLEEP;
210 hdmi->hotplug = hotplug;
212 else if(hotplug == HDMI_HPD_REMOVED)
216 hdmi_sys_show_state(hdmi->state);
217 state_last = hdmi->state;
220 case READ_PARSE_EDID:
221 rc = hdmi_sys_parse_edid(hdmi);
222 if(rc == HDMI_ERROR_SUCESS)
224 hdmi->state = SYSTEM_CONFIG;
225 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD, envp);
227 switch_set_state(&(hdmi->switch_hdmi), 1);
229 #ifdef CONFIG_RK_HDMI_CTL_CODEC
236 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
238 hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
239 rc = hdmi_switch_fb(hdmi, hdmi->vic);
240 if(rc == HDMI_ERROR_SUCESS)
241 hdmi->state = CONFIG_VIDEO;
244 hdmi->display = HDMI_DISABLE;
245 video.vic = hdmi->vic;
246 video.input_mode = VIDEO_INPUT_RGB_YCBCR_444;
247 video.input_color = VIDEO_INPUT_COLOR_RGB;//VIDEO_INPUT_COLOR_YCBCR
248 video.output_mode = hdmi->edid.sink_hdmi;
250 if(hdmi->edid.ycbcr444)
251 video.output_color = VIDEO_OUTPUT_YCBCR444;
252 else if(hdmi->edid.ycbcr422)
253 video.output_color = VIDEO_OUTPUT_YCBCR422;
255 video.output_color = VIDEO_OUTPUT_RGB444;
256 // For DVI, output RGB
257 if(hdmi->edid.sink_hdmi == 0)
258 video.output_color = VIDEO_OUTPUT_RGB444;
260 rc = hdmi->config_video(&video);
261 if(rc == HDMI_ERROR_SUCESS)
263 if(hdmi->edid.sink_hdmi)
264 hdmi->state = CONFIG_AUDIO;
266 hdmi->state = PLAY_BACK;
270 rc = hdmi->config_audio(&(hdmi->audio));
272 if(rc == HDMI_ERROR_SUCESS)
273 hdmi->state = PLAY_BACK;
276 if(hdmi->display != HDMI_ENABLE) {
277 hdmi->control_output(HDMI_ENABLE);
278 hdmi->display = HDMI_ENABLE;
284 if(hdmi->wait == 1) {
285 complete(&hdmi->complete);
292 if(rc != HDMI_ERROR_SUCESS)
297 if(hdmi->state != state_last)
300 }while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
302 hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
303 mutex_unlock(&work_mutex);