Merge remote-tracking branch 'origin/upstream/linux-linaro-lsk-v3.10-android' into...
[firefly-linux-kernel-4.4.55.git] / drivers / misc / scaler / scaler-core.c
1 /*
2  *
3  * Copyright (C) 2012 Rockchip
4  *
5  *---------------------------------
6  * version 1.0 2012-9-13
7  *
8  */
9
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/err.h>
14 #include <linux/delay.h>
15 #include <linux/sysfs.h>
16 #include <linux/fs.h>
17 #include <linux/gpio.h>
18 #include <linux/version.h>
19 #include <linux/pm_runtime.h>
20 #include <asm/uaccess.h>
21 #include <linux/scaler-core.h>
22
23 #define SCALER_CORE_VERSION "v1.0.0"
24 #define SCALER_CORE_NAME "scaler-core"
25 #define SCALER_DEV_NAME "scaler-ctrl"
26
27 static DEFINE_MUTEX(mutex_chips);
28 static DEFINE_MUTEX(mutex_ports);
29
30 static struct scaler_device *sdev = NULL;
31 static unsigned short chip_ids = 0;       //<id only grow>只增不减
32 static unsigned int port_ids = 0;
33 extern int scaler_sysfs_create(struct scaler_device *sdev);
34 extern int scaler_sysfs_remove(struct scaler_device *sdev);
35
36 static const char const *scaler_output_name[] = {
37         "output type",
38         "LVDS",
39         "VGA",
40         "RGB",
41         "HDMI",
42         "DP",
43 };
44
45 const char const *scaler_input_name[] = {
46         "input tpye",
47         "VGA",
48         "RGB",
49         "HDMI",
50         "DP",
51         "DVI",
52         "YPBPR",
53         "YCBCR",
54         "MYDP",
55         "IDP",
56 };
57
58 static const char const *scaler_func_name[] ={
59         "This Scaler Function Type Is:",
60         "convertor",
61         "switch",
62         "full function",
63 };
64
65 static void scaler_led_on(int gpio)
66 {
67         gpio_set_value(gpio, GPIO_HIGH);        
68 }
69 static void scaler_led_off(int gpio)
70 {
71         gpio_set_value(gpio, GPIO_LOW); 
72 }
73
74 static void default_start(void)
75 {
76 }
77
78 static void default_stop(void)
79 {
80 }
81
82 static int default_read(unsigned short reg, int bytes, void *desc)
83 {
84         return 0;
85 }
86
87 static int default_write(unsigned short reg, int bytes, void *desc)
88 {
89         return 0;
90 }
91
92 static int default_parse_cmd(unsigned int cmd, unsigned long arg)
93 {
94         return 0;
95 }
96
97 //alloc chip dev memory and init default value
98 struct scaler_chip_dev *alloc_scaler_chip(void)
99 {
100         struct scaler_chip_dev *p = kzalloc(sizeof(struct scaler_chip_dev), GFP_KERNEL);
101         if (p) {
102                 strcpy(p->name, "unknown");
103                 //init default operation function
104                 p->start = default_start;
105                 p->stop = default_stop;
106                 p->read = default_read;
107                 p->write = default_write;
108                 p->parse_cmd = default_parse_cmd;
109                 //init list head
110                 INIT_LIST_HEAD(&p->next);
111                 INIT_LIST_HEAD(&p->oports);
112                 INIT_LIST_HEAD(&p->iports);
113         }
114         return p;
115 }
116
117 int scaler_init_platform(struct scaler_platform_data *pdata)
118 {
119         printk("%s: init scaler platform\n", SCALER_CORE_NAME);
120
121         if (pdata->init_hw) {
122                 pdata->init_hw();
123                 msleep(5);
124         }
125
126         //power
127         if (pdata->power_gpio > 0) {
128                 if (!gpio_request(pdata->power_gpio, NULL)) {
129                         if (pdata->power_level != GPIO_HIGH && 
130                                         pdata->power_level != GPIO_LOW) {
131                                 printk("%s: power pin level use default high\n", SCALER_CORE_NAME);
132                                 pdata->power_level = GPIO_HIGH;
133                         }
134                         gpio_direction_output(pdata->power_gpio, pdata->power_level); 
135                 }else
136                         printk("%s: request vga power gpio failed\n", SCALER_CORE_NAME);
137         }else
138                 printk("%s: Don't defined power gpio pin\n", SCALER_CORE_NAME);
139
140         //vga 5v en
141         if (pdata->vga5v_gpio > 0) {
142                 if (!gpio_request(pdata->vga5v_gpio, NULL)) {
143                         if (pdata->vga5v_level != GPIO_HIGH && 
144                                         pdata->vga5v_level != GPIO_LOW) {
145                                 printk("%s: vga5ven pin level use default high\n", SCALER_CORE_NAME);
146                                 pdata->vga5v_level = GPIO_HIGH;
147                         }
148                         gpio_direction_output(pdata->vga5v_gpio, pdata->vga5v_level); 
149                 }else
150                         printk("%s: request vga5ven  gpio failed\n", SCALER_CORE_NAME);
151                 msleep(10);
152         }else
153                 printk("%s: Don't defined vga5ven gpio pin\n", SCALER_CORE_NAME);
154         
155         //ddc select
156         if (pdata->ddc_sel_gpio > 0) {
157                 if (!gpio_request(pdata->ddc_sel_gpio, NULL)) {
158                         if (pdata->ddc_sel_level != GPIO_HIGH && 
159                                         pdata->ddc_sel_level != GPIO_LOW) {
160                                 printk("%s: ddc select pin level use default high\n", SCALER_CORE_NAME);
161                                 pdata->ddc_sel_level = GPIO_HIGH;
162                         }
163                         gpio_direction_output(pdata->ddc_sel_gpio, pdata->ddc_sel_level); 
164                 }else
165                         printk("%s: request ddc select gpio failed\n", SCALER_CORE_NAME);
166                 msleep(10);
167         }else
168                 printk("%s: Don't defined ddc select gpio pin\n", SCALER_CORE_NAME);
169 }
170
171 int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *pdata)
172 {
173         int i;
174         struct scaler_output_port *oport = NULL;
175         struct scaler_input_port *iport = NULL;
176
177         if (!chip || !pdata) {
178                 printk("%s: chip or pdata is null.\n", SCALER_CORE_NAME);
179                 return -1;
180         }
181         
182         //set scaler function type
183         if (pdata->func_type > SCALER_FUNC_INVALID && 
184                         pdata->func_type < SCALER_FUNC_NUMS) {
185                 chip->func_type = pdata->func_type;
186         }else {
187                 printk("%s: not defined scaer function type\n", SCALER_CORE_NAME);
188                 chip->func_type = SCALER_FUNC_FULL;
189         }
190         printk("%s: %s %s\n", chip->name, scaler_func_name[0], scaler_func_name[chip->func_type]);
191
192         //set scaler support input type
193         for (i = 0; i < pdata->iport_size; i++) {
194                 iport = kzalloc(sizeof(struct scaler_input_port), GFP_KERNEL);
195                 if (!iport) {
196                     printk("%s: kzalloc input port memeory failed.\n", SCALER_CORE_NAME);
197                     return -1;
198                 }else {
199                         iport->max_hres = 1920;
200                         iport->max_vres = 1080;
201                         iport->freq = 60;
202                         //input port id
203                         mutex_lock(&mutex_ports);
204                         iport->id = ++port_ids;
205                         mutex_unlock(&mutex_ports);
206                         //input port type
207                         iport->type = pdata->iports[i].type;
208                         //the first input port is default 
209                         if (!chip->cur_inport_id) {
210                                 chip->cur_in_type = iport->type;
211                                 chip->cur_inport_id = iport->id;
212                                 printk("%s:  default %s %s\n", chip->name, scaler_input_name[0], scaler_input_name[iport->type]);
213                         }
214
215                         //init and request input gpio of indicator lamp 
216                         if (pdata->iports[i].led_gpio > 0) {
217                                 iport->led_gpio = pdata->iports[i].led_gpio;
218                                 if (!gpio_request(iport->led_gpio, NULL)) {
219                                         gpio_direction_output(iport->led_gpio, GPIO_HIGH);      
220                                 }else {
221                                         printk("%s:  request %s<id,%d> gpio failed\n", chip->name, 
222                                                            scaler_input_name[pdata->iports[i].type], iport->id);
223                                 }
224                         }
225
226                         //add input of chip
227                         list_add_tail(&iport->next, &chip->iports);
228                         printk("%s:  support %s %s<id,%d> led_gpio %d\n", chip->name, scaler_input_name[0], 
229                                              scaler_input_name[pdata->iports[i].type], iport->id, iport->led_gpio);
230                 }//if (!iport)
231         }//for()
232
233         //set scaler output type
234         for (i = 0; i < pdata->oport_size; i++) {
235                 oport = kzalloc(sizeof(struct scaler_output_port), GFP_KERNEL);
236                 if (!oport) {
237                     printk("%s: kzalloc output port memeory failed.\n", SCALER_CORE_NAME);
238                     return -1;
239                 }else {
240                         oport->max_hres = 1920;
241                         oport->max_vres = 1080;
242                         oport->freq = 60;
243                         //output port id
244                         mutex_lock(&mutex_ports);
245                         oport->id = ++port_ids;
246                         mutex_unlock(&mutex_ports);
247                         //output port type
248                         oport->type = pdata->oports[i].type;
249                         //the first output port is default 
250                         if (!chip->cur_outport_id) {
251                                 chip->cur_out_type = oport->type;
252                                 chip->cur_outport_id = oport->id;
253                                 printk("%s:  default %s %s\n", chip->name, scaler_output_name[0], scaler_output_name[oport->type]);
254                         }
255
256                         //init and request output gpio of indicator lamp 
257                         if (pdata->oports[i].led_gpio > 0) {
258                                 oport->led_gpio = pdata->oports[i].led_gpio;
259                                 if (!gpio_request(oport->led_gpio, NULL)) {
260                                         gpio_direction_output(oport->led_gpio, GPIO_HIGH);      
261                                 }else {
262                                         printk("%s:  request %s<id,%d> gpio failed\n", chip->name, scaler_output_name[pdata->oports[i].type], oport->id);
263                                 }
264                         }
265
266                         list_add_tail(&oport->next, &chip->oports);
267                         printk("%s:  support %s %s<id,%d> led_gpio %d\n", chip->name, scaler_output_name[0], 
268                                           scaler_output_name[pdata->oports[i].type], oport->id, oport->led_gpio);
269                 }// if (!oport)
270         }//for()
271
272
273         return 0;
274 }
275
276 //free scaler chip memory
277 void free_scaler_chip(struct scaler_chip_dev *chip)
278 {
279         struct scaler_output_port *out = NULL;
280         struct scaler_input_port *in = NULL;
281         if (chip) {
282                 printk("%s: free %s chip<id:%d> memory resource\n", 
283                                         SCALER_CORE_NAME, chip->name, chip->id);
284                 list_for_each_entry(out, &chip->oports, next) {
285                         kfree(out);
286                 }
287
288                 list_for_each_entry(in, &chip->iports, next) {
289                         if (in->led_gpio > 0)
290                                 gpio_free(in->led_gpio);
291                         kfree(in);
292                 }
293
294                 kfree(chip);
295         }
296 }
297
298 //register chip to scaler core
299 int register_scaler_chip(struct scaler_chip_dev *chip)
300 {
301         int res = -1;
302         struct scaler_input_port *in;
303         struct scaler_output_port *out;
304         
305         if (chip && sdev) {
306                 res = 0;
307
308                 //start chip to process
309                 chip->start();
310
311                 //power on input indicator lamp
312                 list_for_each_entry(in, &chip->iports, next){
313                         if (in->id == chip->cur_inport_id)
314                                 scaler_led_on(in->led_gpio);
315                         else
316                                 scaler_led_off(in->led_gpio);
317                 }
318
319                 //power on output indicator lamp
320                 list_for_each_entry(out, &chip->oports, next){
321                         if (out->id == chip->cur_outport_id)
322                                 scaler_led_on(out->led_gpio);
323                         else
324                                 scaler_led_off(out->led_gpio);
325                 }
326                 //add chip to scaler core
327                 mutex_lock(&mutex_chips);
328                 chip->id = ++chip_ids;  //chip id only grow
329                 list_add_tail(&chip->next, &sdev->chips);
330                 mutex_unlock(&mutex_chips);
331                 printk("%s: register scaler chip %s<id:%d> success.\n", 
332                                      SCALER_CORE_NAME, chip->name, chip->id);
333         }else {
334                 printk("%s: register scaler chip %s<id:%d> failed.\n", 
335                                      SCALER_CORE_NAME, chip->name, chip->id);
336         }
337
338         return res;
339 }
340
341 //unregister chip to scaler core
342 int unregister_scaler_chip(struct scaler_chip_dev *chip)
343 {
344         int res = -1;
345         struct scaler_input_port *in;
346         struct scaler_output_port *out;
347         
348         if (chip && sdev) {
349                 res = 0;
350
351                 chip->stop();
352
353                 //power off input indicator lamp
354                 list_for_each_entry(in, &chip->iports, next){
355                         if (in->id == chip->cur_inport_id)
356                                 scaler_led_off(in->led_gpio);
357                 }
358
359                 //power off output indicator lamp
360                 list_for_each_entry(out, &chip->oports, next){
361                         if (out->id == chip->cur_outport_id)
362                                 scaler_led_off(out->led_gpio);
363                 }
364
365                 //del chip from scaler core
366                 mutex_lock(&mutex_chips);
367                 list_del(&chip->next);
368                 mutex_unlock(&mutex_chips);
369                 printk("%s: unregister scaler chip %s<id:%d> success.\n", __func__, chip->name, chip->id);
370         }
371
372         return res;
373 }
374
375 /***        cdev operate ***/
376 static int scaler_file_open(struct inode *inode, struct file *filp)
377 {
378         return 0;
379 }
380
381 static int scaler_file_close(struct inode *inode, struct file *filp)
382 {
383         return 0;
384 }
385
386 static ssize_t scaler_file_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
387 {
388         return 0;
389 }
390
391 static ssize_t scaler_file_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
392 {
393         return 0;
394 }
395
396 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
397 static long scaler_file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
398 #else
399 static int  scaler_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
400 #endif
401 {
402         int iport_id;
403         struct scaler_chip_dev *chip = NULL;
404         struct scaler_input_port *iport = NULL;
405
406
407         switch(cmd) {
408                 case 0:
409                         printk("get cur input cmd %#x\n", SCALER_IOCTL_GET_CUR_INPUT);
410                         printk("set cur input cmd %#x\n", SCALER_IOCTL_SET_CUR_INPUT);
411                         break;
412                 case SCALER_IOCTL_SET_CUR_INPUT:
413                         //choose input channel;
414                         copy_from_user(&iport_id, (void *)arg, sizeof(int));
415
416                         list_for_each_entry(chip, &sdev->chips, next) {
417                                 if (chip->cur_inport_id != iport_id) {
418                                         list_for_each_entry(iport, &chip->iports, next) {//if iport belong to this chip
419                                                 if (iport->id == iport_id) {
420                                                         chip->cur_inport_id = iport_id;
421                                                         chip->cur_in_type = iport->type;
422                                                         chip->parse_cmd(cmd, arg);
423                                                         break;
424                                                 }
425                                         }//list iports
426                                 }
427                         }//list chips
428
429                         break;
430                 case SCALER_IOCTL_GET_CUR_INPUT:
431                         list_for_each_entry(chip, &sdev->chips, next) {
432                                 iport_id = chip->cur_inport_id;
433                         }//list chips
434                         copy_to_user((void *)arg, &iport_id, sizeof(int));
435                         printk("current input port id %d\n", iport_id);
436                         break;
437                 default:
438                         //default_parse_cmd(cmd, arg);
439                         break;
440         }
441
442
443         return 0;
444 }
445
446 struct file_operations scaler_fops = {
447 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
448                 .unlocked_ioctl =scaler_file_ioctl,
449 #else
450                 .ioctl =scaler_file_ioctl,          //定义所有对scaler操作的cmd
451 #endif
452                 .read =scaler_file_read,
453                 .write = scaler_file_write,
454                 .open = scaler_file_open,
455                 .release = scaler_file_close,
456 };
457
458 //注册一个scaler的字符设备 供别的设备操作scaler
459 static int scaler_register_chrdev(void)
460 {
461     int ret = 0;
462
463     ret = alloc_chrdev_region(&sdev->devno, 0, 1, SCALER_DEV_NAME);
464     if(ret != 0){
465         printk("%s, can't allocate chrdev devno.\n", __func__);
466         return ret;
467     }else {
468         printk("%s: Scaler chrdev devno(%d,%d).\n", __func__, MAJOR(sdev->devno), MINOR(sdev->devno));
469     }   
470                                     
471     // initialize character device driver
472         sdev->cdev = cdev_alloc();
473         if (!sdev->cdev) {
474                 printk("%s: cdev alloc failed.\n", __func__);
475                 goto err1;
476         }
477
478     cdev_init(sdev->cdev, &scaler_fops);
479     sdev->cdev->owner = THIS_MODULE;
480     ret = cdev_add(sdev->cdev, sdev->devno, 1); 
481     if(ret < 0){ 
482         printk("%s, add character device error, ret %d\n", __func__, ret);
483         goto err2;
484     }   
485
486     sdev->class = class_create(THIS_MODULE, "scaler");
487     if(!sdev->class){
488         printk("%s, create class failed\n", __func__);
489         goto err3;
490     }   
491
492     sdev->dev = device_create(sdev->class, NULL, sdev->devno, sdev, SCALER_DEV_NAME);
493         if (!sdev->dev) {
494                 printk("%s: create device failed\n", __func__);
495                 goto err4;
496         }
497         
498
499     return 0;
500
501 err4:
502         class_destroy(sdev->class);
503 err3:
504         cdev_del(sdev->cdev);
505 err2:
506         kfree(sdev->cdev);
507 err1:
508         unregister_chrdev_region(sdev->devno, 1);
509
510         return -1;
511 }
512
513 static void scaler_unregister_chrdev(void)
514 {
515         cdev_del(sdev->cdev);
516         unregister_chrdev_region(sdev->devno, 1);
517         kfree(sdev->cdev);
518         device_destroy(sdev->class, sdev->devno);
519         class_destroy(sdev->class);
520 }
521
522 static int __init rk_scaler_init(void)
523 {
524         printk("%s: SCALER CORE VERSION: %s\n", __func__, SCALER_CORE_VERSION);
525
526         sdev = kzalloc(sizeof(struct scaler_device), GFP_KERNEL);
527         if (!sdev) {
528                 printk("%s: malloc scaler devices failed.\n", __func__);
529                 return -1;
530         }else {
531                 INIT_LIST_HEAD(&sdev->chips);
532         }
533
534         if (scaler_register_chrdev() < 0) {
535                 printk("%s:  scaler register chrdev failed.\n", __func__);
536                 goto err1;
537         }
538
539         if (scaler_sysfs_create(sdev) < 0) {
540                 printk("%s: scaler sysfs create faild.\n", __func__);
541                 goto err2;
542         }
543
544         return 0;
545 err2:
546         scaler_unregister_chrdev();
547 err1:
548         kfree(sdev);
549
550         return -1;
551 }
552
553 static void  __exit rk_scaler_exit(void)
554 {
555         printk("%s\n", __func__);
556         scaler_sysfs_remove(sdev);
557         scaler_unregister_chrdev();
558         kfree(sdev);
559 }
560
561 subsys_initcall(rk_scaler_init);
562 module_exit(rk_scaler_exit);
563
564 MODULE_AUTHOR("linjh <linjh@rock-chips.com>");
565 MODULE_DESCRIPTION("RK Scaler Device Driver");
566 MODULE_LICENSE("GPL");