3 * Copyright (C) 2012 Rockchip
5 *---------------------------------
6 * version 1.0 2012-9-13
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>
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>
23 #define SCALER_CORE_VERSION "v1.0.0"
24 #define SCALER_CORE_NAME "scaler-core"
25 #define SCALER_DEV_NAME "scaler-ctrl"
27 static DEFINE_MUTEX(mutex_chips);
28 static DEFINE_MUTEX(mutex_ports);
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);
36 static const char const *scaler_output_name[] = {
45 const char const *scaler_input_name[] = {
58 static const char const *scaler_func_name[] ={
59 "This Scaler Function Type Is:",
65 static void scaler_led_on(int gpio)
67 gpio_set_value(gpio, GPIO_HIGH);
69 static void scaler_led_off(int gpio)
71 gpio_set_value(gpio, GPIO_LOW);
74 static void default_start(void)
78 static void default_stop(void)
82 static int default_read(unsigned short reg, int bytes, void *desc)
87 static int default_write(unsigned short reg, int bytes, void *desc)
92 static int default_parse_cmd(unsigned int cmd, unsigned long arg)
97 //alloc chip dev memory and init default value
98 struct scaler_chip_dev *alloc_scaler_chip(void)
100 struct scaler_chip_dev *p = kzalloc(sizeof(struct scaler_chip_dev), GFP_KERNEL);
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;
110 INIT_LIST_HEAD(&p->next);
111 INIT_LIST_HEAD(&p->oports);
112 INIT_LIST_HEAD(&p->iports);
117 int scaler_init_platform(struct scaler_platform_data *pdata)
119 printk("%s: init scaler platform\n", SCALER_CORE_NAME);
121 if (pdata->init_hw) {
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;
134 gpio_direction_output(pdata->power_gpio, pdata->power_level);
136 printk("%s: request vga power gpio failed\n", SCALER_CORE_NAME);
138 printk("%s: Don't defined power gpio pin\n", SCALER_CORE_NAME);
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;
148 gpio_direction_output(pdata->vga5v_gpio, pdata->vga5v_level);
150 printk("%s: request vga5ven gpio failed\n", SCALER_CORE_NAME);
153 printk("%s: Don't defined vga5ven gpio pin\n", SCALER_CORE_NAME);
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;
163 gpio_direction_output(pdata->ddc_sel_gpio, pdata->ddc_sel_level);
165 printk("%s: request ddc select gpio failed\n", SCALER_CORE_NAME);
168 printk("%s: Don't defined ddc select gpio pin\n", SCALER_CORE_NAME);
171 int init_scaler_chip(struct scaler_chip_dev *chip, struct scaler_platform_data *pdata)
174 struct scaler_output_port *oport = NULL;
175 struct scaler_input_port *iport = NULL;
177 if (!chip || !pdata) {
178 printk("%s: chip or pdata is null.\n", SCALER_CORE_NAME);
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;
187 printk("%s: not defined scaer function type\n", SCALER_CORE_NAME);
188 chip->func_type = SCALER_FUNC_FULL;
190 printk("%s: %s %s\n", chip->name, scaler_func_name[0], scaler_func_name[chip->func_type]);
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);
196 printk("%s: kzalloc input port memeory failed.\n", SCALER_CORE_NAME);
199 iport->max_hres = 1920;
200 iport->max_vres = 1080;
203 mutex_lock(&mutex_ports);
204 iport->id = ++port_ids;
205 mutex_unlock(&mutex_ports);
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]);
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);
221 printk("%s: request %s<id,%d> gpio failed\n", chip->name,
222 scaler_input_name[pdata->iports[i].type], iport->id);
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);
233 //set scaler output type
234 for (i = 0; i < pdata->oport_size; i++) {
235 oport = kzalloc(sizeof(struct scaler_output_port), GFP_KERNEL);
237 printk("%s: kzalloc output port memeory failed.\n", SCALER_CORE_NAME);
240 oport->max_hres = 1920;
241 oport->max_vres = 1080;
244 mutex_lock(&mutex_ports);
245 oport->id = ++port_ids;
246 mutex_unlock(&mutex_ports);
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]);
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);
262 printk("%s: request %s<id,%d> gpio failed\n", chip->name, scaler_output_name[pdata->oports[i].type], oport->id);
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);
276 //free scaler chip memory
277 void free_scaler_chip(struct scaler_chip_dev *chip)
279 struct scaler_output_port *out = NULL;
280 struct scaler_input_port *in = NULL;
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) {
288 list_for_each_entry(in, &chip->iports, next) {
289 if (in->led_gpio > 0)
290 gpio_free(in->led_gpio);
298 //register chip to scaler core
299 int register_scaler_chip(struct scaler_chip_dev *chip)
302 struct scaler_input_port *in;
303 struct scaler_output_port *out;
308 //start chip to process
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);
316 scaler_led_off(in->led_gpio);
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);
324 scaler_led_off(out->led_gpio);
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);
334 printk("%s: register scaler chip %s<id:%d> failed.\n",
335 SCALER_CORE_NAME, chip->name, chip->id);
341 //unregister chip to scaler core
342 int unregister_scaler_chip(struct scaler_chip_dev *chip)
345 struct scaler_input_port *in;
346 struct scaler_output_port *out;
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);
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);
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);
375 /*** cdev operate ***/
376 static int scaler_file_open(struct inode *inode, struct file *filp)
381 static int scaler_file_close(struct inode *inode, struct file *filp)
386 static ssize_t scaler_file_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
391 static ssize_t scaler_file_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
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)
399 static int scaler_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
403 struct scaler_chip_dev *chip = NULL;
404 struct scaler_input_port *iport = NULL;
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);
412 case SCALER_IOCTL_SET_CUR_INPUT:
413 //choose input channel;
414 copy_from_user(&iport_id, (void *)arg, sizeof(int));
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);
430 case SCALER_IOCTL_GET_CUR_INPUT:
431 list_for_each_entry(chip, &sdev->chips, next) {
432 iport_id = chip->cur_inport_id;
434 copy_to_user((void *)arg, &iport_id, sizeof(int));
435 printk("current input port id %d\n", iport_id);
438 //default_parse_cmd(cmd, arg);
446 struct file_operations scaler_fops = {
447 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
448 .unlocked_ioctl =scaler_file_ioctl,
450 .ioctl =scaler_file_ioctl, //定义所有对scaler操作的cmd
452 .read =scaler_file_read,
453 .write = scaler_file_write,
454 .open = scaler_file_open,
455 .release = scaler_file_close,
458 //注册一个scaler的字符设备 供别的设备操作scaler
459 static int scaler_register_chrdev(void)
463 ret = alloc_chrdev_region(&sdev->devno, 0, 1, SCALER_DEV_NAME);
465 printk("%s, can't allocate chrdev devno.\n", __func__);
468 printk("%s: Scaler chrdev devno(%d,%d).\n", __func__, MAJOR(sdev->devno), MINOR(sdev->devno));
471 // initialize character device driver
472 sdev->cdev = cdev_alloc();
474 printk("%s: cdev alloc failed.\n", __func__);
478 cdev_init(sdev->cdev, &scaler_fops);
479 sdev->cdev->owner = THIS_MODULE;
480 ret = cdev_add(sdev->cdev, sdev->devno, 1);
482 printk("%s, add character device error, ret %d\n", __func__, ret);
486 sdev->class = class_create(THIS_MODULE, "scaler");
488 printk("%s, create class failed\n", __func__);
492 sdev->dev = device_create(sdev->class, NULL, sdev->devno, sdev, SCALER_DEV_NAME);
494 printk("%s: create device failed\n", __func__);
502 class_destroy(sdev->class);
504 cdev_del(sdev->cdev);
508 unregister_chrdev_region(sdev->devno, 1);
513 static void scaler_unregister_chrdev(void)
515 cdev_del(sdev->cdev);
516 unregister_chrdev_region(sdev->devno, 1);
518 device_destroy(sdev->class, sdev->devno);
519 class_destroy(sdev->class);
522 static int __init rk_scaler_init(void)
524 printk("%s: SCALER CORE VERSION: %s\n", __func__, SCALER_CORE_VERSION);
526 sdev = kzalloc(sizeof(struct scaler_device), GFP_KERNEL);
528 printk("%s: malloc scaler devices failed.\n", __func__);
531 INIT_LIST_HEAD(&sdev->chips);
534 if (scaler_register_chrdev() < 0) {
535 printk("%s: scaler register chrdev failed.\n", __func__);
539 if (scaler_sysfs_create(sdev) < 0) {
540 printk("%s: scaler sysfs create faild.\n", __func__);
546 scaler_unregister_chrdev();
553 static void __exit rk_scaler_exit(void)
555 printk("%s\n", __func__);
556 scaler_sysfs_remove(sdev);
557 scaler_unregister_chrdev();
561 subsys_initcall(rk_scaler_init);
562 module_exit(rk_scaler_exit);
564 MODULE_AUTHOR("linjh <linjh@rock-chips.com>");
565 MODULE_DESCRIPTION("RK Scaler Device Driver");
566 MODULE_LICENSE("GPL");