1 #include <linux/kernel.h>
2 #include <linux/delay.h>
3 #include <linux/interrupt.h>
4 #include <linux/rockchip/common.h>
5 #include <dt-bindings/clock/rk_system_status.h>
8 #define HDMI_MAX_TRY_TIMES 1
11 static char *envp[] = { "INTERFACE=HDMI", NULL };
13 static void hdmi_sys_show_state(struct hdmi *hdmi)
15 switch (hdmi->state) {
17 hdmi_dbg(hdmi->dev, "HDMI_SLEEP\n");
20 hdmi_dbg(hdmi->dev, "HDMI_INITIAL\n");
23 hdmi_dbg(hdmi->dev, "WAIT_HOTPLUG\n");
26 hdmi_dbg(hdmi->dev, "READ_PARSE_EDID\n");
28 case WAIT_HDMI_ENABLE:
29 hdmi_dbg(hdmi->dev, "WAIT_HDMI_ENABLE\n");
32 hdmi_dbg(hdmi->dev, "SYSTEM_CONFIG\n");
35 hdmi_dbg(hdmi->dev, "CONFIG_VIDEO\n");
38 hdmi_dbg(hdmi->dev, "CONFIG_AUDIO\n");
41 hdmi_dbg(hdmi->dev, "PLAY_BACK\n");
44 hdmi_dbg(hdmi->dev, "Unkown State %d\n", hdmi->state);
49 int hdmi_sys_init(struct hdmi *hdmi)
51 hdmi->hotplug = HDMI_HPD_REMOVED;
52 hdmi->state = HDMI_SLEEP;
53 hdmi->enable = HDMI_ENABLE;
54 hdmi->autoconfig = HDMI_AUTO_CONFIGURE;
55 hdmi->display = HDMI_DISABLE;
57 hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
58 hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
59 hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
60 hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORD_LENGTH;
62 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
63 INIT_LIST_HEAD(&hdmi->edid.modelist);
67 void hdmi_sys_remove(struct hdmi *hdmi)
71 audio_need = hdmi->edid.base_audio_support == 1
72 && hdmi->edid.sink_hdmi == 1;
74 fb_destroy_modelist(&hdmi->edid.modelist);
75 kfree(hdmi->edid.audio);
76 if (hdmi->edid.specs) {
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, 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);
90 switch_set_state(&(hdmi->switch_hdmi), 0);
92 rockchip_clear_system_status(SYS_STATUS_HDMI);
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) {
113 hdmi->command = HDMI_CONFIG_NONE;
115 case HDMI_CONFIG_ENABLE:
117 mutex_lock(&hdmi->enable_mutex);
118 if (!hdmi->enable || hdmi->suspend) {
119 if (hdmi->hotplug != HDMI_HPD_REMOVED) {
120 hdmi->hotplug = HDMI_HPD_REMOVED;
121 hdmi_sys_remove(hdmi);
123 hdmi->state = HDMI_SLEEP;
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;
150 if (hdmi->wait == 1) {
151 complete(&hdmi->complete);
157 } else if (state == HDMI_SLEEP)
158 state = WAIT_HOTPLUG;
162 static DEFINE_MUTEX(work_mutex);
164 void hdmi_work(struct work_struct *work)
166 int hotplug, state_last;
167 int rc = HDMI_ERROR_SUCESS, trytimes = 0;
168 struct hdmi_video_para video;
169 struct delayed_work *delay_work =
170 container_of(work, struct delayed_work, work);
171 struct hdmi *hdmi = container_of(delay_work, struct hdmi, delay_work);
173 mutex_lock(&work_mutex);
174 /* Process hdmi command */
175 hdmi->state = hdmi_process_command(hdmi);
177 if (!hdmi->enable || hdmi->suspend) {
178 mutex_unlock(&work_mutex);
181 hotplug = hdmi->detect_hotplug(hdmi);
182 hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __func__,
183 hotplug, hdmi->hotplug);
185 if (hotplug != hdmi->hotplug) {
186 if (hotplug == HDMI_HPD_ACTIVED) {
189 hdmi->state = READ_PARSE_EDID;
190 } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
191 hdmi->hotplug = hotplug;
192 hdmi_sys_remove(hdmi);
193 if (hotplug == HDMI_HPD_REMOVED)
194 hdmi_sys_sleep(hdmi);
196 hdmi->state = WAIT_HOTPLUG;
199 if (hdmi->wait == 1) {
200 complete(&hdmi->complete);
203 mutex_unlock(&work_mutex);
205 } else if (hotplug == HDMI_HPD_REMOVED) {
206 hdmi->state = HDMI_SLEEP;
209 hdmi->hotplug = hotplug;
210 } else if (hotplug == HDMI_HPD_REMOVED)
211 hdmi_sys_sleep(hdmi);
214 hdmi_sys_show_state(hdmi);
215 state_last = hdmi->state;
216 switch (hdmi->state) {
217 case READ_PARSE_EDID:
218 rc = hdmi_sys_parse_edid(hdmi);
219 if (rc == HDMI_ERROR_SUCESS) {
220 hdmi->state = SYSTEM_CONFIG;
221 kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD,
224 "[%s] base_audio_support =%d,sink_hdmi = %d\n",
226 hdmi->edid.base_audio_support,
227 hdmi->edid.sink_hdmi);
229 if (hdmi->edid.base_audio_support == 1
230 && hdmi->edid.sink_hdmi == 1)
231 switch_set_state(&(hdmi->switch_hdmi),
234 rockchip_set_system_status(SYS_STATUS_HDMI);
241 if (hdmi->autoconfig)
242 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
245 hdmi_find_best_mode(hdmi, hdmi->vic);
246 rc = hdmi_switch_fb(hdmi, hdmi->vic);
247 if (rc == HDMI_ERROR_SUCESS)
248 hdmi->state = CONFIG_VIDEO;
251 hdmi->display = HDMI_DISABLE;
252 hdmi_init_video_para(hdmi, &video);
253 rc = hdmi->config_video(hdmi, &video);
254 if (rc == HDMI_ERROR_SUCESS) {
255 if (hdmi->edid.sink_hdmi)
256 hdmi->state = CONFIG_AUDIO;
258 hdmi->state = PLAY_BACK;
262 rc = hdmi->config_audio(hdmi, &(hdmi->audio));
264 if (rc == HDMI_ERROR_SUCESS)
265 hdmi->state = PLAY_BACK;
268 if (hdmi->display != HDMI_ENABLE) {
269 hdmi->control_output(hdmi, HDMI_ENABLE);
270 hdmi->display = HDMI_ENABLE;
275 if (hdmi->wait == 1) {
276 complete(&hdmi->complete);
283 if (rc != HDMI_ERROR_SUCESS) {
287 if (hdmi->state != state_last)
290 } while ((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS))
291 && trytimes < HDMI_MAX_TRY_TIMES);
293 hdmi_dbg(hdmi->dev, "[%s] done\n", __func__);
294 mutex_unlock(&work_mutex);