2 * Copyright (C) 2012 Spreadtrum Communications Inc.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/miscdevice.h>
16 #include <linux/platform_device.h>
17 #include <linux/proc_fs.h>
18 #include <linux/slab.h>
19 #include <linux/delay.h>
20 #include <asm/uaccess.h>
21 #include <video/sprd_scale_k.h>
22 #include <linux/kthread.h>
24 #include <linux/of_device.h>
25 #include <linux/vmalloc.h>
27 #include "img_scale.h"
28 #include "compat_img_scale.h"
32 #include <soc/sprd/hardware.h>
35 #define SCALE_DEVICE_NAME "sprd_scale"
36 #define SCALE_TIMEOUT 5000/*ms*/
37 #define SCALE_MINOR MISC_DYNAMIC_MINOR
38 #define SC_COEFF_BUF_SIZE (24 << 10)
40 static void scale_k_irq(void *fd)
42 struct scale_k_file *scale_file = (struct scale_k_file *)fd;
45 printk("scale_k_irq error: hand is null");
49 SCALE_TRACE("sc done.\n");
51 up(&scale_file->scale_done_sem);
54 static void scale_k_file_init(struct scale_k_file *fd, struct scale_k_private *scale_private)
56 fd->scale_private = scale_private;
58 sema_init(&fd->scale_done_sem, 0);
60 fd->drv_private.scale_fd = (void*)fd;
61 fd->drv_private.path_info.coeff_addr = scale_private->coeff_addr;
63 spin_lock_init(&fd->drv_private.scale_drv_lock);
64 sema_init(&fd->drv_private.path_info.done_sem, 0);
67 static int scale_k_open(struct inode *node, struct file *file)
70 struct scale_k_file *fd = NULL;
71 struct scale_k_private *scale_private = NULL;
72 struct miscdevice *md = file->private_data;
76 printk("scale_k_open error: miscdevice is null \n");
79 scale_private = (struct scale_k_private *)md->this_device->platform_data;
82 printk("scale_k_open error: scale_private is null \n");
86 fd = vzalloc(sizeof(*fd));
89 printk("scale_k_open error: alloc \n");
92 fd->dn = md->this_device->of_node;
93 scale_k_file_init(fd, scale_private);
95 file->private_data = fd;
97 SCALE_TRACE("scale_k_open fd=%p ret=%d\n", fd, ret);
103 ssize_t scale_k_read(struct file *file, char __user *u_data, size_t cnt, loff_t *cnt_ret)
107 (void)file; (void)cnt; (void)cnt_ret;
109 if (cnt < sizeof(uint32_t)) {
110 printk("scale_k_read error: wrong size of u_data: %ld \n", cnt);
114 rt_word[0] = SCALE_LINE_BUF_LENGTH;
115 rt_word[1] = SCALE_SC_COEFF_MAX;
117 return copy_to_user(u_data, (void*)rt_word, (uint32_t)(2 * sizeof(uint32_t)));
120 static int scale_k_release(struct inode *node, struct file *file)
122 struct scale_k_file *fd = NULL;
123 struct scale_k_private *scale_private = NULL;
125 fd = file->private_data;
130 scale_private = fd->scale_private;
131 if (!scale_private) {
135 down(&scale_private->start_sem);
136 up(&scale_private->start_sem);
141 file->private_data = NULL;
144 SCALE_TRACE("scale_k_release\n");
149 static void sprd_img_print_reg(void)
151 uint32_t* reg_buf = NULL;
152 uint32_t reg_buf_len = 0x400;
154 uint32_t print_len = 0, print_cnt = 0;
155 reg_buf = (uint32_t*)vzalloc(reg_buf_len);
158 ret = dcam_read_registers(reg_buf, ®_buf_len);
163 printk("dcam registers \n");
164 while (print_len < reg_buf_len) {
165 printk("offset 0x%03x : 0x%08x, 0x%08x, 0x%08x, 0x%08x \n",
168 reg_buf[print_cnt+1],
169 reg_buf[print_cnt+2],
170 reg_buf[print_cnt+3]);
178 static long scale_k_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
181 struct scale_k_private *scale_private;
182 struct scale_k_file *fd;
183 struct scale_frame_param_t frame_params;
184 struct scale_slice_param_t slice_params;
186 fd = file->private_data;
189 printk("scale_k_ioctl error: fd null \n");
193 scale_private = fd->scale_private;
194 if (!scale_private) {
196 printk("scale_k_ioctl erro: scale private null \n");
203 down(&scale_private->start_sem);
205 ret = scale_k_module_en(fd->dn);
207 printk("rot_k_ioctl erro: scale_module_en\n");
208 up(&scale_private->start_sem);
212 ret = scale_k_isr_reg(scale_k_irq, &fd->drv_private);
214 printk("rot_k_ioctl error: scale_k_isr_reg\n");
215 scale_k_module_dis(fd->dn);
216 up(&scale_private->start_sem);
221 ret = copy_from_user(&frame_params, (struct scale_frame_param_t *)arg, sizeof(frame_params));
223 printk("rot_k_ioctl error: get frame param info \n");
224 scale_k_module_dis(fd->dn);
225 up(&scale_private->start_sem);
229 ret = scale_k_start(&frame_params, &fd->drv_private.path_info);
231 printk("rot_k_ioctl error: frame start \n");
232 scale_k_module_dis(fd->dn);
233 up(&scale_private->start_sem);
239 ret = down_timeout(&fd->scale_done_sem, msecs_to_jiffies(SCALE_TIMEOUT));
241 printk("scale_k_ioctl error: interruptible time out\n");
242 sprd_img_print_reg();
248 scale_k_module_dis(fd->dn);
250 up(&scale_private->start_sem);
252 case SCALE_IO_CONTINUE:
253 /*Caution: slice scale is not supported by current driver.Please do not use it*/
254 ret = copy_from_user(&slice_params, (struct scale_slice_param_t *)arg, sizeof(slice_params));
256 printk("rot_k_ioctl error: get slice param info \n");
260 ret = scale_k_continue(&slice_params, &fd->drv_private.path_info);
262 printk("rot_k_ioctl error: continue \n");
276 scale_k_module_dis(fd->dn);
277 up(&scale_private->start_sem);
281 static struct file_operations scale_fops = {
282 .owner = THIS_MODULE,
283 .open = scale_k_open,
284 .read = scale_k_read,
285 .unlocked_ioctl = scale_k_ioctl,
286 .compat_ioctl = compat_scale_k_ioctl,
287 .release = scale_k_release,
290 static struct miscdevice scale_dev = {
291 .minor = SCALE_MINOR,
292 .name = SCALE_DEVICE_NAME,
296 int scale_k_probe(struct platform_device *pdev)
299 struct scale_k_private *scale_private;
301 scale_private = devm_kzalloc(&pdev->dev, sizeof(*scale_private), GFP_KERNEL);
302 if (!scale_private) {
305 scale_private->coeff_addr = (void *)vzalloc(SC_COEFF_BUF_SIZE);
306 if (!scale_private->coeff_addr) {
307 devm_kfree(&pdev->dev, scale_private);
310 sema_init(&scale_private->start_sem, 1);
312 platform_set_drvdata(pdev, scale_private);
314 ret = misc_register(&scale_dev);
316 printk("scale_k_probe error: ret=%d\n", ret);
321 scale_dev.this_device->of_node = pdev->dev.of_node;
322 scale_dev.this_device->platform_data = (void *)scale_private;
327 vfree(scale_private->coeff_addr);
328 devm_kfree(&pdev->dev, scale_private);
329 platform_set_drvdata(pdev, NULL);
334 static int scale_k_remove(struct platform_device *pdev)
336 struct scale_k_private *scale_private;
338 scale_private = platform_get_drvdata(pdev);
343 misc_deregister(&scale_dev);
344 if (scale_private->coeff_addr) {
345 vfree(scale_private->coeff_addr);
347 devm_kfree(&pdev->dev, scale_private);
348 platform_set_drvdata(pdev, NULL);
354 static const struct of_device_id of_match_table_scale[] = {
355 { .compatible = "sprd,sprd_scale", },
359 static struct platform_driver scale_driver =
361 .probe = scale_k_probe,
362 .remove = scale_k_remove,
364 .owner = THIS_MODULE,
365 .name = SCALE_DEVICE_NAME,
366 .of_match_table = of_match_ptr(of_match_table_scale),
370 int __init scale_k_init(void)
372 if (platform_driver_register(&scale_driver) != 0) {
373 printk("platform scale device register Failed \n");
380 void scale_k_exit(void)
382 platform_driver_unregister(&scale_driver);
385 module_init(scale_k_init);
386 module_exit(scale_k_exit);
387 MODULE_DESCRIPTION("Sprd Scale Driver");
388 MODULE_LICENSE("GPL");