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 *modelist = &hdmi->edid.modelist;
46 static int hdmi_set_mode(struct rk_display_device *device,
47 struct fb_videomode *mode)
49 struct hdmi *hdmi = device->priv_data;
50 struct display_modelist *display_modelist =
51 container_of(mode, struct display_modelist, mode);
54 mutex_lock(&hdmi->lock);
57 vic = hdmi_find_best_mode(hdmi, 0);
60 vic = display_modelist->vic;
63 if (vic && hdmi->vic != vic) {
65 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
66 hdmi_submit_work(hdmi, HDMI_SET_VIDEO, 0, NULL);
68 mutex_unlock(&hdmi->lock);
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))
119 pr_warn("warning: sink not support input 3d mode %d", mode);
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 int hdmi_get_debug(struct rk_display_device *device, char *buf)
307 struct hdmi *hdmi = device->priv_data;
313 len += snprintf(buf+len, PAGE_SIZE, "EDID status:%s\n",
314 hdmi->edid.status ? "False" : "Okay");
315 len += snprintf(buf+len, PAGE_SIZE, "Raw Data:");
316 mutex_lock(&hdmi->lock);
317 for (i = 0; i < HDMI_MAX_EDID_BLOCK; i++) {
318 if (!hdmi->edid.raw[i])
320 buff = hdmi->edid.raw[i];
321 for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
323 len += snprintf(buf+len, PAGE_SIZE, "\n");
324 len += snprintf(buf+len, PAGE_SIZE, "0x%02x, ",
328 mutex_unlock(&hdmi->lock);
332 static struct rk_display_ops hdmi_display_ops = {
333 .setenable = hdmi_set_enable,
334 .getenable = hdmi_get_enable,
335 .getstatus = hdmi_get_status,
336 .getmodelist = hdmi_get_modelist,
337 .setmode = hdmi_set_mode,
338 .getmode = hdmi_get_mode,
339 .set3dmode = hdmi_set_3dmode,
340 .get3dmode = hdmi_get_3dmode,
341 .getedidaudioinfo = hdmi_get_edidaudioinfo,
342 .setcolor = hdmi_set_color,
343 .getcolor = hdmi_get_color,
344 .getmonspecs = hdmi_get_monspecs,
345 .setscale = hdmi_set_scale,
346 .getscale = hdmi_get_scale,
347 .getdebug = hdmi_get_debug,
350 static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
352 struct hdmi *hdmi = devdata;
354 device->owner = THIS_MODULE;
355 strcpy(device->type, "HDMI");
356 device->priority = DISPLAY_PRIORITY_HDMI;
357 device->name = hdmi->property->name;
358 device->property = hdmi->property->display;
359 device->priv_data = devdata;
360 device->ops = &hdmi_display_ops;
364 static struct rk_display_driver display_hdmi = {
365 .probe = hdmi_display_probe,
368 struct rk_display_device *hdmi_register_display_sysfs(struct hdmi *hdmi,
369 struct device *parent)
371 return rk_display_device_register(&display_hdmi, parent, hdmi);
374 void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
377 rk_display_device_unregister(hdmi->ddev);