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);
56 mutex_lock(&hdmi->lock);
59 vic = hdmi_find_best_mode(hdmi, 0);
62 vic = display_modelist->vic;
65 if (vic && hdmi->vic != vic) {
67 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
68 hdmi_submit_work(hdmi, HDMI_SET_VIDEO, 0, NULL);
70 mutex_unlock(&hdmi->lock);
74 static int hdmi_get_mode(struct rk_display_device *device,
75 struct fb_videomode *mode)
77 struct hdmi *hdmi = device->priv_data;
78 struct fb_videomode *vmode;
84 vmode = (struct fb_videomode *)
85 hdmi_vic_to_videomode(hdmi->vic);
86 if (unlikely(vmode == NULL))
89 if (hdmi->vic & HDMI_VIDEO_YUV420)
92 memset(mode, 0, sizeof(struct fb_videomode));
97 static int hdmi_set_3dmode(struct rk_display_device *device, int mode)
99 struct hdmi *hdmi = device->priv_data;
100 struct list_head *modelist, *pos;
101 struct display_modelist *display_modelist = NULL;
105 mutex_lock(&hdmi->lock);
106 modelist = &hdmi->edid.modelist;
107 list_for_each(pos, modelist) {
109 list_entry(pos, struct display_modelist, list);
110 if (hdmi->vic == display_modelist->vic)
113 display_modelist = NULL;
115 mutex_unlock(&hdmi->lock);
116 if (!display_modelist)
119 if ((mode != HDMI_3D_NONE) &&
120 ((display_modelist->format_3d & (1 << mode)) == 0))
121 pr_warn("warning: sink not support input 3d mode %d", mode);
123 if (hdmi->mode_3d != mode) {
124 hdmi->mode_3d = mode;
125 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
126 hdmi_submit_work(hdmi, HDMI_SET_3D, 0, NULL);
131 static int hdmi_get_3dmode(struct rk_display_device *device)
133 struct hdmi *hdmi = device->priv_data;
138 return hdmi->mode_3d;
141 /*CEA 861-E: Audio Coding Type
142 sync width enum hdmi_audio_type
144 static const char * const audioformatstr[] = {
146 "LPCM", /*HDMI_AUDIO_LPCM = 1,*/
147 "AC3", /*HDMI_AUDIO_AC3,*/
148 "MPEG1", /*HDMI_AUDIO_MPEG1,*/
149 "MP3", /*HDMI_AUDIO_MP3,*/
150 "MPEG2", /*HDMI_AUDIO_MPEG2,*/
151 "AAC-LC", /*HDMI_AUDIO_AAC_LC, AAC*/
152 "DTS", /*HDMI_AUDIO_DTS,*/
153 "ATARC", /*HDMI_AUDIO_ATARC,*/
154 "DSD", /*HDMI_AUDIO_DSD, One bit Audio */
155 "E-AC3", /*HDMI_AUDIO_E_AC3,*/
156 "DTS-HD", /*HDMI_AUDIO_DTS_HD,*/
157 "MLP", /*HDMI_AUDIO_MLP,*/
158 "DST", /*HDMI_AUDIO_DST,*/
159 "WMA-PRO", /*HDMI_AUDIO_WMA_PRO*/
162 static int hdmi_get_edidaudioinfo(struct rk_display_device *device,
163 char *audioinfo, int len)
165 struct hdmi *hdmi = device->priv_data;
167 struct hdmi_audio *audio;
172 memset(audioinfo, 0x00, len);
173 mutex_lock(&hdmi->lock);
174 /*printk("hdmi:edid: audio_num: %d\n", hdmi->edid.audio_num);*/
175 for (i = 0; i < hdmi->edid.audio_num; i++) {
176 audio = &(hdmi->edid.audio[i]);
177 if (audio->type < 1 || audio->type > HDMI_AUDIO_WMA_PRO) {
178 pr_info("audio type: unsupported.");
181 size = strlen(audioformatstr[audio->type]);
182 memcpy(audioinfo, audioformatstr[audio->type], size);
183 audioinfo[size] = ',';
184 audioinfo += (size+1);
186 mutex_unlock(&hdmi->lock);
190 static int hdmi_get_color(struct rk_display_device *device, char *buf)
192 struct hdmi *hdmi = device->priv_data;
195 mutex_lock(&hdmi->lock);
196 mode = (1 << HDMI_COLOR_RGB_0_255);
197 if (hdmi->edid.sink_hdmi) {
198 mode |= (1 << HDMI_COLOR_RGB_16_235);
199 if (hdmi->edid.ycbcr422)
200 mode |= (1 << HDMI_COLOR_YCBCR422);
201 if (hdmi->edid.ycbcr444)
202 mode |= (1 << HDMI_COLOR_YCBCR444);
204 i = snprintf(buf, PAGE_SIZE,
205 "Supported Color Mode: %d\n", mode);
206 i += snprintf(buf + i, PAGE_SIZE - i,
207 "Current Color Mode: %d\n", hdmi->colormode);
209 mode = (1 << 1); /* 24 bit*/
210 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS &&
211 hdmi->property->feature & SUPPORT_DEEP_10BIT)
212 mode |= (1 << HDMI_DEEP_COLOR_30BITS);
213 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_36BITS &&
214 hdmi->property->feature & SUPPORT_DEEP_12BIT)
215 mode |= (1 << HDMI_DEEP_COLOR_36BITS);
216 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_48BITS &&
217 hdmi->property->feature & SUPPORT_DEEP_16BIT)
218 mode |= (1 << HDMI_DEEP_COLOR_48BITS);
219 i += snprintf(buf + i, PAGE_SIZE - i,
220 "Supported Color Depth: %d\n", mode);
221 i += snprintf(buf + i, PAGE_SIZE - i,
222 "Current Color Depth: %d\n", hdmi->colordepth);
223 mutex_unlock(&hdmi->lock);
227 static int hdmi_set_color(struct rk_display_device *device,
228 const char *buf, int len)
230 struct hdmi *hdmi = device->priv_data;
233 if (!strncmp(buf, "mode", 4)) {
234 if (sscanf(buf, "mode=%d", &value) == -1)
236 pr_debug("current mode is %d input mode is %d\n",
237 hdmi->colormode, value);
238 if (hdmi->colormode != value)
239 hdmi->colormode = value;
240 } else if (!strncmp(buf, "depth", 5)) {
241 if (sscanf(buf, "depth=%d", &value) == -1)
243 pr_debug("current depth is %d input mode is %d\n",
244 hdmi->colordepth, value);
245 if (hdmi->colordepth != value)
246 hdmi->colordepth = value;
248 pr_err("%s unkown event\n", __func__);
251 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
252 hdmi_submit_work(hdmi, HDMI_SET_COLOR, 0, NULL);
256 static int hdmi_set_scale(struct rk_display_device *device, int direction,
259 struct hdmi *hdmi = device->priv_data;
261 if (!hdmi || value < 0 || value > 100)
267 if (direction == DISPLAY_SCALE_X)
268 hdmi->xscale = value;
269 else if (direction == DISPLAY_SCALE_Y)
270 hdmi->yscale = value;
273 rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
277 static int hdmi_get_scale(struct rk_display_device *device, int direction)
279 struct hdmi *hdmi = device->priv_data;
284 if (direction == DISPLAY_SCALE_X)
286 else if (direction == DISPLAY_SCALE_Y)
292 static int hdmi_get_monspecs(struct rk_display_device *device,
293 struct fb_monspecs *monspecs)
295 struct hdmi *hdmi = device->priv_data;
300 mutex_lock(&hdmi->lock);
301 if (hdmi->edid.specs)
302 *monspecs = *(hdmi->edid.specs);
303 mutex_unlock(&hdmi->lock);
307 static struct rk_display_ops hdmi_display_ops = {
308 .setenable = hdmi_set_enable,
309 .getenable = hdmi_get_enable,
310 .getstatus = hdmi_get_status,
311 .getmodelist = hdmi_get_modelist,
312 .setmode = hdmi_set_mode,
313 .getmode = hdmi_get_mode,
314 .set3dmode = hdmi_set_3dmode,
315 .get3dmode = hdmi_get_3dmode,
316 .getedidaudioinfo = hdmi_get_edidaudioinfo,
317 .setcolor = hdmi_set_color,
318 .getcolor = hdmi_get_color,
319 .getmonspecs = hdmi_get_monspecs,
320 .setscale = hdmi_set_scale,
321 .getscale = hdmi_get_scale,
324 static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
326 struct hdmi *hdmi = devdata;
328 device->owner = THIS_MODULE;
329 strcpy(device->type, "HDMI");
330 device->priority = DISPLAY_PRIORITY_HDMI;
331 device->name = hdmi->property->name;
332 device->property = hdmi->property->display;
333 device->priv_data = devdata;
334 device->ops = &hdmi_display_ops;
338 static struct rk_display_driver display_hdmi = {
339 .probe = hdmi_display_probe,
342 struct rk_display_device *hdmi_register_display_sysfs(struct hdmi *hdmi,
343 struct device *parent)
345 return rk_display_device_register(&display_hdmi, parent, hdmi);
348 void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
351 rk_display_device_unregister(hdmi->ddev);