1 #include <linux/ctype.h>
2 #include <linux/string.h>
3 #include <linux/display-sys.h>
4 #include <linux/interrupt.h>
5 #include "rockchip-hdmi.h"
7 static int hdmi_get_enable(struct rk_display_device *device)
9 struct hdmi *hdmi = device->priv_data;
12 enable = hdmi->enable;
16 static int hdmi_set_enable(struct rk_display_device *device, int enable)
18 struct hdmi *hdmi = device->priv_data;
21 hdmi_submit_work(hdmi, HDMI_DISABLE_CTL, 0, NULL);
23 hdmi_submit_work(hdmi, HDMI_ENABLE_CTL, 0, NULL);
27 static int hdmi_get_status(struct rk_display_device *device)
29 struct hdmi *hdmi = device->priv_data;
31 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
37 static int hdmi_get_modelist(struct rk_display_device *device,
38 struct list_head **modelist)
40 struct hdmi *hdmi = device->priv_data;
42 mutex_lock(&hdmi->lock);
43 *modelist = &hdmi->edid.modelist;
44 mutex_unlock(&hdmi->lock);
48 static int hdmi_set_mode(struct rk_display_device *device,
49 struct fb_videomode *mode)
51 struct hdmi *hdmi = device->priv_data;
52 struct display_modelist *display_modelist =
53 container_of(mode, struct display_modelist, mode);
58 vic = hdmi_find_best_mode(hdmi, 0);
61 vic = display_modelist->vic;
64 if (vic && hdmi->vic != vic) {
66 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
67 hdmi_submit_work(hdmi, HDMI_SET_VIDEO, 0, NULL);
72 static int hdmi_get_mode(struct rk_display_device *device,
73 struct fb_videomode *mode)
75 struct hdmi *hdmi = device->priv_data;
76 struct fb_videomode *vmode;
82 vmode = (struct fb_videomode *)
83 hdmi_vic_to_videomode(hdmi->vic);
84 if (unlikely(vmode == NULL))
87 if (hdmi->vic & HDMI_VIDEO_YUV420)
90 memset(mode, 0, sizeof(struct fb_videomode));
95 static int hdmi_set_3dmode(struct rk_display_device *device, int mode)
97 struct hdmi *hdmi = device->priv_data;
98 struct list_head *modelist, *pos;
99 struct display_modelist *display_modelist = NULL;
103 mutex_lock(&hdmi->lock);
104 modelist = &hdmi->edid.modelist;
105 list_for_each(pos, modelist) {
107 list_entry(pos, struct display_modelist, list);
108 if (hdmi->vic == display_modelist->vic)
111 display_modelist = NULL;
113 mutex_unlock(&hdmi->lock);
114 if (!display_modelist)
117 if ((mode != HDMI_3D_NONE) &&
118 ((display_modelist->format_3d & (1 << mode)) == 0))
121 if (hdmi->mode_3d != mode) {
122 hdmi->mode_3d = mode;
123 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
124 hdmi_submit_work(hdmi, HDMI_SET_3D, 0, NULL);
129 static int hdmi_get_3dmode(struct rk_display_device *device)
131 struct hdmi *hdmi = device->priv_data;
136 return hdmi->mode_3d;
139 /*CEA 861-E: Audio Coding Type
140 sync width enum hdmi_audio_type
142 static const char * const audioformatstr[] = {
144 "LPCM", /*HDMI_AUDIO_LPCM = 1,*/
145 "AC3", /*HDMI_AUDIO_AC3,*/
146 "MPEG1", /*HDMI_AUDIO_MPEG1,*/
147 "MP3", /*HDMI_AUDIO_MP3,*/
148 "MPEG2", /*HDMI_AUDIO_MPEG2,*/
149 "AAC-LC", /*HDMI_AUDIO_AAC_LC, AAC*/
150 "DTS", /*HDMI_AUDIO_DTS,*/
151 "ATARC", /*HDMI_AUDIO_ATARC,*/
152 "DSD", /*HDMI_AUDIO_DSD, One bit Audio */
153 "E-AC3", /*HDMI_AUDIO_E_AC3,*/
154 "DTS-HD", /*HDMI_AUDIO_DTS_HD,*/
155 "MLP", /*HDMI_AUDIO_MLP,*/
156 "DST", /*HDMI_AUDIO_DST,*/
157 "WMA-PRO", /*HDMI_AUDIO_WMA_PRO*/
160 static int hdmi_get_edidaudioinfo(struct rk_display_device *device,
161 char *audioinfo, int len)
163 struct hdmi *hdmi = device->priv_data;
165 struct hdmi_audio *audio;
170 memset(audioinfo, 0x00, len);
171 mutex_lock(&hdmi->lock);
172 /*printk("hdmi:edid: audio_num: %d\n", hdmi->edid.audio_num);*/
173 for (i = 0; i < hdmi->edid.audio_num; i++) {
174 audio = &(hdmi->edid.audio[i]);
175 if (audio->type < 1 || audio->type > HDMI_AUDIO_WMA_PRO) {
176 pr_info("audio type: unsupported.");
179 size = strlen(audioformatstr[audio->type]);
180 memcpy(audioinfo, audioformatstr[audio->type], size);
181 audioinfo[size] = ',';
182 audioinfo += (size+1);
184 mutex_unlock(&hdmi->lock);
188 static int hdmi_get_color(struct rk_display_device *device, char *buf)
190 struct hdmi *hdmi = device->priv_data;
193 mutex_lock(&hdmi->lock);
194 mode = (1 << HDMI_COLOR_RGB_0_255);
195 if (hdmi->edid.sink_hdmi) {
196 mode |= (1 << HDMI_COLOR_RGB_16_235);
197 if (hdmi->edid.ycbcr422)
198 mode |= (1 << HDMI_COLOR_YCBCR422);
199 if (hdmi->edid.ycbcr444)
200 mode |= (1 << HDMI_COLOR_YCBCR444);
202 i = snprintf(buf, PAGE_SIZE,
203 "Supported Color Mode: %d\n", mode);
204 i += snprintf(buf + i, PAGE_SIZE - i,
205 "Current Color Mode: %d\n", hdmi->colormode);
207 mode = (1 << 1); /* 24 bit*/
208 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS &&
209 hdmi->property->feature & SUPPORT_DEEP_10BIT)
210 mode |= (1 << HDMI_DEEP_COLOR_30BITS);
211 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_36BITS &&
212 hdmi->property->feature & SUPPORT_DEEP_12BIT)
213 mode |= (1 << HDMI_DEEP_COLOR_36BITS);
214 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_48BITS &&
215 hdmi->property->feature & SUPPORT_DEEP_16BIT)
216 mode |= (1 << HDMI_DEEP_COLOR_48BITS);
217 i += snprintf(buf + i, PAGE_SIZE - i,
218 "Supported Color Depth: %d\n", mode);
219 i += snprintf(buf + i, PAGE_SIZE - i,
220 "Current Color Depth: %d\n", hdmi->colordepth);
221 mutex_unlock(&hdmi->lock);
225 static int hdmi_set_color(struct rk_display_device *device,
226 const char *buf, int len)
228 struct hdmi *hdmi = device->priv_data;
231 if (!strncmp(buf, "mode", 4)) {
232 if (sscanf(buf, "mode=%d", &value) == -1)
234 pr_debug("current mode is %d input mode is %d\n",
235 hdmi->colormode, value);
236 if (hdmi->colormode != value)
237 hdmi->colormode = value;
238 } else if (!strncmp(buf, "depth", 5)) {
239 if (sscanf(buf, "depth=%d", &value) == -1)
241 pr_debug("current depth is %d input mode is %d\n",
242 hdmi->colordepth, value);
243 if (hdmi->colordepth != value)
244 hdmi->colordepth = value;
246 pr_err("%s unkown event\n", __func__);
249 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
250 hdmi_submit_work(hdmi, HDMI_SET_COLOR, 0, NULL);
254 static int hdmi_set_scale(struct rk_display_device *device, int direction,
257 struct hdmi *hdmi = device->priv_data;
259 if (!hdmi || value < 0 || value > 100)
265 if (direction == DISPLAY_SCALE_X)
266 hdmi->xscale = value;
267 else if (direction == DISPLAY_SCALE_Y)
268 hdmi->yscale = value;
271 rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
275 static int hdmi_get_scale(struct rk_display_device *device, int direction)
277 struct hdmi *hdmi = device->priv_data;
282 if (direction == DISPLAY_SCALE_X)
284 else if (direction == DISPLAY_SCALE_Y)
290 static int hdmi_get_monspecs(struct rk_display_device *device,
291 struct fb_monspecs *monspecs)
293 struct hdmi *hdmi = device->priv_data;
298 mutex_lock(&hdmi->lock);
299 if (hdmi->edid.specs)
300 *monspecs = *(hdmi->edid.specs);
301 mutex_unlock(&hdmi->lock);
305 static struct rk_display_ops hdmi_display_ops = {
306 .setenable = hdmi_set_enable,
307 .getenable = hdmi_get_enable,
308 .getstatus = hdmi_get_status,
309 .getmodelist = hdmi_get_modelist,
310 .setmode = hdmi_set_mode,
311 .getmode = hdmi_get_mode,
312 .set3dmode = hdmi_set_3dmode,
313 .get3dmode = hdmi_get_3dmode,
314 .getedidaudioinfo = hdmi_get_edidaudioinfo,
315 .setcolor = hdmi_set_color,
316 .getcolor = hdmi_get_color,
317 .getmonspecs = hdmi_get_monspecs,
318 .setscale = hdmi_set_scale,
319 .getscale = hdmi_get_scale,
322 static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
324 struct hdmi *hdmi = devdata;
326 device->owner = THIS_MODULE;
327 strcpy(device->type, "HDMI");
328 device->priority = DISPLAY_PRIORITY_HDMI;
329 device->name = hdmi->property->name;
330 device->property = hdmi->property->display;
331 device->priv_data = devdata;
332 device->ops = &hdmi_display_ops;
336 static struct rk_display_driver display_hdmi = {
337 .probe = hdmi_display_probe,
340 struct rk_display_device *hdmi_register_display_sysfs(struct hdmi *hdmi,
341 struct device *parent)
343 return rk_display_device_register(&display_hdmi, parent, hdmi);
346 void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
349 rk_display_device_unregister(hdmi->ddev);