rk hdmi: add node to get TV audio&video info
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rk_hdmi_sysfs.c
1 #include <linux/ctype.h>
2 #include <linux/string.h>
3 #include <linux/display-sys.h>
4 #include <linux/interrupt.h>
5 #include "rk_hdmi.h"
6
7 static int hdmi_get_enable(struct rk_display_device *device)
8 {
9         struct hdmi *hdmi = device->priv_data;
10         int enable;
11
12         mutex_lock(&hdmi->enable_mutex);
13         enable = hdmi->enable;
14         mutex_unlock(&hdmi->enable_mutex);
15
16         return enable;
17 }
18
19 static int hdmi_set_enable(struct rk_display_device *device, int enable)
20 {
21         struct hdmi *hdmi = device->priv_data;
22
23         mutex_lock(&hdmi->enable_mutex);
24         if (hdmi->enable == enable) {
25                 mutex_unlock(&hdmi->enable_mutex);
26                 return 0;
27         }
28         hdmi->enable = enable;
29
30         if (hdmi->suspend) {
31                 mutex_unlock(&hdmi->enable_mutex);
32                 return 0;
33         }
34
35         if (enable == 0) {
36                 if (hdmi->irq)
37                         disable_irq(hdmi->irq);
38                 mutex_unlock(&hdmi->enable_mutex);
39                 hdmi->command = HDMI_CONFIG_ENABLE;
40                 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
41         } else {
42                 if (hdmi->irq)
43                         enable_irq(hdmi->irq);
44                 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
45                 mutex_unlock(&hdmi->enable_mutex);
46         }
47         return 0;
48 }
49
50 static int hdmi_get_status(struct rk_display_device *device)
51 {
52         struct hdmi *hdmi = device->priv_data;
53
54         if (hdmi->hotplug == HDMI_HPD_ACTIVED)
55                 return 1;
56         else
57                 return 0;
58 }
59
60 static int hdmi_get_modelist(struct rk_display_device *device,
61                              struct list_head **modelist)
62 {
63         struct hdmi *hdmi = device->priv_data;
64
65         if (!hdmi->hotplug)
66                 return -1;
67         *modelist = &hdmi->edid.modelist;
68         return 0;
69 }
70
71 static int hdmi_set_mode(struct rk_display_device *device,
72                          struct fb_videomode *mode)
73 {
74         struct hdmi *hdmi = device->priv_data;
75         int vic = hdmi_videomode_to_vic(mode);
76
77         hdmi->autoconfig = HDMI_DISABLE;
78         if (vic && hdmi->vic != vic) {
79                 hdmi->vic = vic;
80                 if (!hdmi->hotplug)
81                         return 0;
82                 hdmi->command = HDMI_CONFIG_VIDEO;
83                 init_completion(&hdmi->complete);
84                 hdmi->wait = 1;
85                 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
86                 wait_for_completion_interruptible_timeout(&hdmi->complete,
87                                                           msecs_to_jiffies
88                                                           (10000));
89         }
90         return 0;
91 }
92
93 static int hdmi_get_mode(struct rk_display_device *device,
94                          struct fb_videomode *mode)
95 {
96         struct hdmi *hdmi = device->priv_data;
97         struct fb_videomode *vmode;
98
99         if (!hdmi->hotplug)
100                 return -1;
101
102         vmode = (struct fb_videomode *)hdmi_vic_to_videomode(hdmi->vic);
103         if (unlikely(vmode == NULL))
104                 return -1;
105         *mode = *vmode;
106         return 0;
107 }
108
109 static int hdmi_set_scale(struct rk_display_device *device, int direction,
110                           int value)
111 {
112         struct hdmi *hdmi = device->priv_data;
113
114         if (!hdmi || value < 0 || value > 100)
115                 return -1;
116
117         if (!hdmi->hotplug)
118                 return 0;
119
120         if (direction == DISPLAY_SCALE_X)
121                 hdmi->xscale = value;
122         else if (direction == DISPLAY_SCALE_Y)
123                 hdmi->yscale = value;
124         else
125                 return -1;
126         rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
127         return 0;
128 }
129
130 static int hdmi_get_scale(struct rk_display_device *device, int direction)
131 {
132         struct hdmi *hdmi = device->priv_data;
133
134         if (!hdmi)
135                 return -1;
136
137         if (direction == DISPLAY_SCALE_X)
138                 return hdmi->xscale;
139         else if (direction == DISPLAY_SCALE_Y)
140                 return hdmi->yscale;
141         else
142                 return -1;
143 }
144 static int hdmi_set_debug(struct rk_display_device *device, int cmd)
145 {
146         struct hdmi *hdmi = device->priv_data;
147
148         if (!hdmi)
149                 return -1;
150         if (hdmi->ops && hdmi->ops->hdmi_debug)
151                 hdmi->ops->hdmi_debug(hdmi,cmd);
152
153         return 0;
154 }
155 //CEA 861-E: Audio Coding Type
156 //sync width enum hdmi_audio_type
157 static const char* const sAudioFormatStr[] = {
158         "",
159         "LPCM",         //HDMI_AUDIO_LPCM = 1,
160         "AC3",          //HDMI_AUDIO_AC3,
161         "MPEG1",        //HDMI_AUDIO_MPEG1,
162         "MP3",          //HDMI_AUDIO_MP3,
163         "MPEG2",        //HDMI_AUDIO_MPEG2,
164         "AAC-LC",       //HDMI_AUDIO_AAC_LC,            //AAC
165         "DTS",          //HDMI_AUDIO_DTS,
166         "ATARC",        //HDMI_AUDIO_ATARC,
167         "DSD",          //HDMI_AUDIO_DSD,                       //One bit Audio
168         "E-AC3",        //HDMI_AUDIO_E_AC3,
169         "DTS-HD",       //HDMI_AUDIO_DTS_HD,
170         "MLP",          //HDMI_AUDIO_MLP,
171         "DST",          //HDMI_AUDIO_DST,
172         "WMA-PRO",      //HDMI_AUDIO_WMA_PRO
173 };
174
175 static int hdmi_get_edidaudioinfo(struct rk_display_device *device, char *audioinfo, int len)
176 {
177         struct hdmi *hdmi = device->priv_data;
178         int i=0;
179         int size=0;
180         struct hdmi_audio *audio;
181         if(!hdmi)
182                 return -1;
183
184         memset(audioinfo, 0x00, len);
185         mutex_lock(&hdmi->lock);
186         //printk("hdmi:edid: audio_num: %d\n", hdmi->edid.audio_num);
187         for(i = 0; i < hdmi->edid.audio_num; i++)
188         {
189                 audio = &(hdmi->edid.audio[i]);
190                 if(audio->type<1 || audio->type>HDMI_AUDIO_WMA_PRO){
191                         printk("audio type: unsupported.");
192                         continue;
193                 }
194                 size = strlen(sAudioFormatStr[audio->type]);
195                 //printk("size: %d, type: %s\n", size, sAudioFormatStr[audio->type]);
196                 memcpy(audioinfo, sAudioFormatStr[audio->type], size);
197                 audioinfo[size]=',';
198                 audioinfo += (size+1);
199         }
200         mutex_unlock(&hdmi->lock);
201         return 0;
202 }
203
204
205 static int hdmi_get_monspecs(struct rk_display_device *device, struct fb_monspecs *monspecs)
206 {
207         struct hdmi *hdmi = device->priv_data;
208
209         if (!hdmi)
210                 return -1;
211
212         mutex_lock(&hdmi->lock);
213         if(hdmi->edid.specs)
214                 *monspecs = *(hdmi->edid.specs);
215         mutex_unlock(&hdmi->lock);
216         return 0;
217 }
218
219 struct rk_display_ops hdmi_display_ops = {
220         .setenable = hdmi_set_enable,
221         .getenable = hdmi_get_enable,
222         .getstatus = hdmi_get_status,
223         .getmodelist = hdmi_get_modelist,
224         .setmode = hdmi_set_mode,
225         .getmode = hdmi_get_mode,
226         .setscale = hdmi_set_scale,
227         .getscale = hdmi_get_scale,
228         .setdebug = hdmi_set_debug,
229         .getedidaudioinfo = hdmi_get_edidaudioinfo,
230         .getmonspecs = hdmi_get_monspecs,
231 };
232
233 #if 1
234 static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
235 {
236         device->owner = THIS_MODULE;
237         strcpy(device->type, "HDMI");
238         device->priority = DISPLAY_PRIORITY_HDMI;
239 /*
240         device->name = kmalloc(strlen(name), GFP_KERNEL);
241         if(device->name)
242                 strcpy(device->name, name);
243 */
244         device->priv_data = devdata;
245         device->ops = &hdmi_display_ops;
246         return 1;
247 }
248
249 static struct rk_display_driver display_hdmi = {
250         .probe = hdmi_display_probe,
251 };
252
253 #ifdef CONFIG_DRM_ROCKCHIP
254 extern void rk_drm_display_register(struct rk_display_ops *extend_ops,
255                                     void *displaydata, int type);
256 #endif
257
258 void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent)
259 {
260         hdmi->ddev =
261             rk_display_device_register(&display_hdmi, parent, hdmi);
262 #ifdef CONFIG_DRM_ROCKCHIP
263         rk_drm_display_register(&hdmi_display_ops, hdmi, SCREEN_HDMI);
264 #endif
265 }
266
267 void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
268 {
269         if (hdmi->ddev)
270                 rk_display_device_unregister(hdmi->ddev);
271 }
272 #endif