| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Authors: Sylwester Nawrocki <s.nawrocki@samsung.com> |
|---|
| 7 | 8 | * Younghwan Joo <yhwan.joo@samsung.com> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 10 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 11 | | - * published by the Free Software Foundation. |
|---|
| 12 | 9 | */ |
|---|
| 13 | 10 | #define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__ |
|---|
| 14 | 11 | |
|---|
| 15 | 12 | #include <linux/device.h> |
|---|
| 16 | 13 | #include <linux/debugfs.h> |
|---|
| 17 | 14 | #include <linux/delay.h> |
|---|
| 18 | | -#include <linux/dma-contiguous.h> |
|---|
| 19 | 15 | #include <linux/errno.h> |
|---|
| 20 | 16 | #include <linux/firmware.h> |
|---|
| 21 | 17 | #include <linux/interrupt.h> |
|---|
| .. | .. |
|---|
| 144 | 140 | dev_err(&is->pdev->dev, "clock %s enable failed\n", |
|---|
| 145 | 141 | fimc_is_clocks[i]); |
|---|
| 146 | 142 | for (--i; i >= 0; i--) |
|---|
| 147 | | - clk_disable(is->clocks[i]); |
|---|
| 143 | + clk_disable_unprepare(is->clocks[i]); |
|---|
| 148 | 144 | return ret; |
|---|
| 149 | 145 | } |
|---|
| 150 | 146 | pr_debug("enabled clock: %s\n", fimc_is_clocks[i]); |
|---|
| .. | .. |
|---|
| 217 | 213 | |
|---|
| 218 | 214 | if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) { |
|---|
| 219 | 215 | of_node_put(child); |
|---|
| 216 | + of_node_put(i2c_bus); |
|---|
| 220 | 217 | return ret; |
|---|
| 221 | 218 | } |
|---|
| 222 | 219 | index++; |
|---|
| .. | .. |
|---|
| 344 | 341 | return -ENOMEM; |
|---|
| 345 | 342 | |
|---|
| 346 | 343 | is->memory.size = FIMC_IS_CPU_MEM_SIZE; |
|---|
| 347 | | - memset(is->memory.vaddr, 0, is->memory.size); |
|---|
| 348 | 344 | |
|---|
| 349 | 345 | dev_info(dev, "FIMC-IS CPU memory base: %#x\n", (u32)is->memory.paddr); |
|---|
| 350 | 346 | |
|---|
| .. | .. |
|---|
| 656 | 652 | |
|---|
| 657 | 653 | int fimc_is_hw_initialize(struct fimc_is *is) |
|---|
| 658 | 654 | { |
|---|
| 659 | | - const int config_ids[] = { |
|---|
| 655 | + static const int config_ids[] = { |
|---|
| 660 | 656 | IS_SC_PREVIEW_STILL, IS_SC_PREVIEW_VIDEO, |
|---|
| 661 | 657 | IS_SC_CAPTURE_STILL, IS_SC_CAPTURE_VIDEO |
|---|
| 662 | 658 | }; |
|---|
| .. | .. |
|---|
| 738 | 734 | return 0; |
|---|
| 739 | 735 | } |
|---|
| 740 | 736 | |
|---|
| 741 | | -static int fimc_is_log_show(struct seq_file *s, void *data) |
|---|
| 737 | +static int fimc_is_show(struct seq_file *s, void *data) |
|---|
| 742 | 738 | { |
|---|
| 743 | 739 | struct fimc_is *is = s->private; |
|---|
| 744 | 740 | const u8 *buf = is->memory.vaddr + FIMC_IS_DEBUG_REGION_OFFSET; |
|---|
| .. | .. |
|---|
| 752 | 748 | return 0; |
|---|
| 753 | 749 | } |
|---|
| 754 | 750 | |
|---|
| 755 | | -static int fimc_is_debugfs_open(struct inode *inode, struct file *file) |
|---|
| 756 | | -{ |
|---|
| 757 | | - return single_open(file, fimc_is_log_show, inode->i_private); |
|---|
| 758 | | -} |
|---|
| 759 | | - |
|---|
| 760 | | -static const struct file_operations fimc_is_debugfs_fops = { |
|---|
| 761 | | - .open = fimc_is_debugfs_open, |
|---|
| 762 | | - .read = seq_read, |
|---|
| 763 | | - .llseek = seq_lseek, |
|---|
| 764 | | - .release = single_release, |
|---|
| 765 | | -}; |
|---|
| 751 | +DEFINE_SHOW_ATTRIBUTE(fimc_is); |
|---|
| 766 | 752 | |
|---|
| 767 | 753 | static void fimc_is_debugfs_remove(struct fimc_is *is) |
|---|
| 768 | 754 | { |
|---|
| .. | .. |
|---|
| 770 | 756 | is->debugfs_entry = NULL; |
|---|
| 771 | 757 | } |
|---|
| 772 | 758 | |
|---|
| 773 | | -static int fimc_is_debugfs_create(struct fimc_is *is) |
|---|
| 759 | +static void fimc_is_debugfs_create(struct fimc_is *is) |
|---|
| 774 | 760 | { |
|---|
| 775 | | - struct dentry *dentry; |
|---|
| 776 | | - |
|---|
| 777 | 761 | is->debugfs_entry = debugfs_create_dir("fimc_is", NULL); |
|---|
| 778 | 762 | |
|---|
| 779 | | - dentry = debugfs_create_file("fw_log", S_IRUGO, is->debugfs_entry, |
|---|
| 780 | | - is, &fimc_is_debugfs_fops); |
|---|
| 781 | | - if (!dentry) |
|---|
| 782 | | - fimc_is_debugfs_remove(is); |
|---|
| 783 | | - |
|---|
| 784 | | - return is->debugfs_entry == NULL ? -EIO : 0; |
|---|
| 763 | + debugfs_create_file("fw_log", S_IRUGO, is->debugfs_entry, is, |
|---|
| 764 | + &fimc_is_fops); |
|---|
| 785 | 765 | } |
|---|
| 786 | 766 | |
|---|
| 787 | 767 | static int fimc_is_runtime_resume(struct device *dev); |
|---|
| .. | .. |
|---|
| 849 | 829 | goto err_irq; |
|---|
| 850 | 830 | } |
|---|
| 851 | 831 | |
|---|
| 852 | | - ret = pm_runtime_get_sync(dev); |
|---|
| 832 | + ret = pm_runtime_resume_and_get(dev); |
|---|
| 853 | 833 | if (ret < 0) |
|---|
| 854 | | - goto err_pm; |
|---|
| 834 | + goto err_pm_disable; |
|---|
| 855 | 835 | |
|---|
| 856 | 836 | vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); |
|---|
| 857 | 837 | |
|---|
| .. | .. |
|---|
| 867 | 847 | if (ret < 0) |
|---|
| 868 | 848 | goto err_pm; |
|---|
| 869 | 849 | |
|---|
| 870 | | - ret = fimc_is_debugfs_create(is); |
|---|
| 871 | | - if (ret < 0) |
|---|
| 872 | | - goto err_sd; |
|---|
| 850 | + fimc_is_debugfs_create(is); |
|---|
| 873 | 851 | |
|---|
| 874 | 852 | ret = fimc_is_request_firmware(is, FIMC_IS_FW_FILENAME); |
|---|
| 875 | 853 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 882 | 860 | |
|---|
| 883 | 861 | err_dfs: |
|---|
| 884 | 862 | fimc_is_debugfs_remove(is); |
|---|
| 885 | | -err_sd: |
|---|
| 886 | 863 | fimc_is_unregister_subdevs(is); |
|---|
| 887 | 864 | err_pm: |
|---|
| 865 | + pm_runtime_put_noidle(dev); |
|---|
| 888 | 866 | if (!pm_runtime_enabled(dev)) |
|---|
| 889 | 867 | fimc_is_runtime_suspend(dev); |
|---|
| 868 | +err_pm_disable: |
|---|
| 869 | + pm_runtime_disable(dev); |
|---|
| 890 | 870 | err_irq: |
|---|
| 891 | 871 | free_irq(is->irq, is); |
|---|
| 892 | 872 | err_clk: |
|---|