Message ID | 20181105073054.24407-12-lkundrak@v3.sk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | media: make Marvell camera work on DT-based OLPC XO-1.75 | expand |
Hi Lubomir, I love your patch! Yet something to improve: [auto build test ERROR on linuxtv-media/master] [also build test ERROR on v4.20-rc1 next-20181105] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Lubomir-Rintel/media-ov7670-hook-s_power-onto-v4l2-core/20181105-163336 base: git://linuxtv.org/media_tree.git master config: ia64-allmodconfig (attached as .config) compiler: ia64-linux-gcc (GCC) 8.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=8.1.0 make.cross ARCH=ia64 All error/warnings (new ones prefixed by >>): In file included from drivers/media/platform/marvell-ccic/cafe-driver.c:38: >> drivers/media/platform/marvell-ccic/mcam-core.h:129:16: error: field 'mclk_hw' has incomplete type struct clk_hw mclk_hw; ^~~~~~~ -- In file included from drivers/media/platform/marvell-ccic/mmp-driver.c:30: >> drivers/media/platform/marvell-ccic/mcam-core.h:129:16: error: field 'mclk_hw' has incomplete type struct clk_hw mclk_hw; ^~~~~~~ drivers/media/platform/marvell-ccic/mmp-driver.c: In function 'mmpcam_probe': >> drivers/media/platform/marvell-ccic/mmp-driver.c:302:8: error: implicit declaration of function 'of_clk_add_provider'; did you mean 'of_clk_get_from_provider'? [-Werror=implicit-function-declaration] ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, ^~~~~~~~~~~~~~~~~~~ of_clk_get_from_provider >> drivers/media/platform/marvell-ccic/mmp-driver.c:302:47: error: 'of_clk_src_simple_get' undeclared (first use in this function); did you mean 'ida_simple_get'? ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, ^~~~~~~~~~~~~~~~~~~~~ ida_simple_get drivers/media/platform/marvell-ccic/mmp-driver.c:302:47: note: each undeclared identifier is reported only once for each function it appears in cc1: some warnings being treated as errors -- In file included from drivers/media/platform/marvell-ccic/mcam-core.c:35: >> drivers/media/platform/marvell-ccic/mcam-core.h:129:16: error: field 'mclk_hw' has incomplete type struct clk_hw mclk_hw; ^~~~~~~ In file included from include/linux/kernel.h:10, from drivers/media/platform/marvell-ccic/mcam-core.c:9: drivers/media/platform/marvell-ccic/mcam-core.c: In function 'mclk_prepare': include/linux/kernel.h:997:32: error: dereferencing pointer to incomplete type 'struct clk_hw' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~ include/linux/compiler.h:353:9: note: in definition of macro '__compiletime_assert' if (!(condition)) \ ^~~~~~~~~ include/linux/compiler.h:373:2: note: in expansion of macro '_compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:45:37: note: in expansion of macro 'compiletime_assert' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^~~~~~~~~~~~~~~~~~ include/linux/kernel.h:997:2: note: in expansion of macro 'BUILD_BUG_ON_MSG' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~~~~~~ include/linux/kernel.h:997:20: note: in expansion of macro '__same_type' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:952:28: note: in expansion of macro 'container_of' struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw); ^~~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c: At top level: >> drivers/media/platform/marvell-ccic/mcam-core.c:1004:21: error: variable 'mclk_ops' has initializer but incomplete type static const struct clk_ops mclk_ops = { ^~~~~~~ >> drivers/media/platform/marvell-ccic/mcam-core.c:1005:3: error: 'const struct clk_ops' has no member named 'prepare' .prepare = mclk_prepare, ^~~~~~~ >> drivers/media/platform/marvell-ccic/mcam-core.c:1005:13: warning: excess elements in struct initializer .prepare = mclk_prepare, ^~~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1005:13: note: (near initialization for 'mclk_ops') >> drivers/media/platform/marvell-ccic/mcam-core.c:1006:3: error: 'const struct clk_ops' has no member named 'unprepare' .unprepare = mclk_unprepare, ^~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1006:15: warning: excess elements in struct initializer .unprepare = mclk_unprepare, ^~~~~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1006:15: note: (near initialization for 'mclk_ops') >> drivers/media/platform/marvell-ccic/mcam-core.c:1007:3: error: 'const struct clk_ops' has no member named 'enable' .enable = mclk_enable, ^~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1007:12: warning: excess elements in struct initializer .enable = mclk_enable, ^~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1007:12: note: (near initialization for 'mclk_ops') >> drivers/media/platform/marvell-ccic/mcam-core.c:1008:3: error: 'const struct clk_ops' has no member named 'disable' .disable = mclk_disable, ^~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1008:13: warning: excess elements in struct initializer .disable = mclk_disable, ^~~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1008:13: note: (near initialization for 'mclk_ops') >> drivers/media/platform/marvell-ccic/mcam-core.c:1009:3: error: 'const struct clk_ops' has no member named 'recalc_rate' .recalc_rate = mclk_recalc_rate, ^~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1009:17: warning: excess elements in struct initializer .recalc_rate = mclk_recalc_rate, ^~~~~~~~~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c:1009:17: note: (near initialization for 'mclk_ops') drivers/media/platform/marvell-ccic/mcam-core.c: In function 'mccic_register': >> drivers/media/platform/marvell-ccic/mcam-core.c:1895:9: error: variable 'mclk_init' has initializer but incomplete type struct clk_init_data mclk_init = { }; ^~~~~~~~~~~~~ >> drivers/media/platform/marvell-ccic/mcam-core.c:1895:23: error: storage size of 'mclk_init' isn't known struct clk_init_data mclk_init = { }; ^~~~~~~~~ >> drivers/media/platform/marvell-ccic/mcam-core.c:1963:14: error: implicit declaration of function 'devm_clk_register'; did you mean 'device_register'? [-Werror=implicit-function-declaration] cam->mclk = devm_clk_register(cam->dev, &cam->mclk_hw); ^~~~~~~~~~~~~~~~~ device_register drivers/media/platform/marvell-ccic/mcam-core.c:1895:23: warning: unused variable 'mclk_init' [-Wunused-variable] struct clk_init_data mclk_init = { }; ^~~~~~~~~ drivers/media/platform/marvell-ccic/mcam-core.c: At top level: >> drivers/media/platform/marvell-ccic/mcam-core.c:1004:29: error: storage size of 'mclk_ops' isn't known static const struct clk_ops mclk_ops = { ^~~~~~~~ cc1: some warnings being treated as errors vim +/mclk_hw +129 drivers/media/platform/marvell-ccic/mcam-core.h 94 95 /* 96 * A description of one of our devices. 97 * Locking: controlled by s_mutex. Certain fields, however, require 98 * the dev_lock spinlock; they are marked as such by comments. 99 * dev_lock is also required for access to device registers. 100 */ 101 struct mcam_camera { 102 /* 103 * These fields should be set by the platform code prior to 104 * calling mcam_register(). 105 */ 106 unsigned char __iomem *regs; 107 unsigned regs_size; /* size in bytes of the register space */ 108 spinlock_t dev_lock; 109 struct device *dev; /* For messages, dma alloc */ 110 enum mcam_chip_id chip_id; 111 enum mcam_buffer_mode buffer_mode; 112 113 int mclk_src; /* which clock source the mclk derives from */ 114 int mclk_div; /* Clock Divider Value for MCLK */ 115 116 enum v4l2_mbus_type bus_type; 117 /* MIPI support */ 118 /* The dphy config value, allocated in board file 119 * dphy[0]: DPHY3 120 * dphy[1]: DPHY5 121 * dphy[2]: DPHY6 122 */ 123 int *dphy; 124 bool mipi_enabled; /* flag whether mipi is enabled already */ 125 int lane; /* lane number */ 126 127 /* clock tree support */ 128 struct clk *clk[NR_MCAM_CLK]; > 129 struct clk_hw mclk_hw; 130 struct clk *mclk; 131 132 /* 133 * Callbacks from the core to the platform code. 134 */ 135 int (*plat_power_up) (struct mcam_camera *cam); 136 void (*plat_power_down) (struct mcam_camera *cam); 137 void (*calc_dphy) (struct mcam_camera *cam); 138 139 /* 140 * Everything below here is private to the mcam core and 141 * should not be touched by the platform code. 142 */ 143 struct v4l2_device v4l2_dev; 144 struct v4l2_ctrl_handler ctrl_handler; 145 enum mcam_state state; 146 unsigned long flags; /* Buffer status, mainly (dev_lock) */ 147 148 struct mcam_frame_state frame_state; /* Frame state counter */ 149 /* 150 * Subsystem structures. 151 */ 152 struct video_device vdev; 153 struct v4l2_async_notifier notifier; 154 struct v4l2_async_subdev asd; 155 struct v4l2_subdev *sensor; 156 157 /* Videobuf2 stuff */ 158 struct vb2_queue vb_queue; 159 struct list_head buffers; /* Available frames */ 160 161 unsigned int nbufs; /* How many are alloc'd */ 162 int next_buf; /* Next to consume (dev_lock) */ 163 164 char bus_info[32]; /* querycap bus_info */ 165 166 /* DMA buffers - vmalloc mode */ 167 #ifdef MCAM_MODE_VMALLOC 168 unsigned int dma_buf_size; /* allocated size */ 169 void *dma_bufs[MAX_DMA_BUFS]; /* Internal buffer addresses */ 170 dma_addr_t dma_handles[MAX_DMA_BUFS]; /* Buffer bus addresses */ 171 struct tasklet_struct s_tasklet; 172 #endif 173 unsigned int sequence; /* Frame sequence number */ 174 unsigned int buf_seq[MAX_DMA_BUFS]; /* Sequence for individual bufs */ 175 176 /* DMA buffers - DMA modes */ 177 struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS]; 178 179 /* Mode-specific ops, set at open time */ 180 void (*dma_setup)(struct mcam_camera *cam); 181 void (*frame_complete)(struct mcam_camera *cam, int frame); 182 183 /* Current operating parameters */ 184 struct v4l2_pix_format pix_format; 185 u32 mbus_code; 186 187 /* Locks */ 188 struct mutex s_mutex; /* Access to this structure */ 189 }; 190 191 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Lubomir, url: https://github.com/0day-ci/linux/commits/Lubomir-Rintel/media-ov7670-hook-s_power-onto-v4l2-core/20181105-163336 base: git://linuxtv.org/media_tree.git master smatch warnings: drivers/media/platform/marvell-ccic/mcam-core.c:1682 mcam_v4l_open() warn: inconsistent returns 'mutex:&cam->s_mutex'. Locked on: line 1673 Unlocked on: line 1682 # https://github.com/0day-ci/linux/commit/a4f7d692c7067355da433bbb534531a4e1a55ac6 git remote add linux-review https://github.com/0day-ci/linux git remote update linux-review git checkout a4f7d692c7067355da433bbb534531a4e1a55ac6 vim +1682 drivers/media/platform/marvell-ccic/mcam-core.c abfa3df3 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-11 1656 abfa3df3 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-11 1657 /* ---------------------------------------------------------------------- */ abfa3df3 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-11 1658 /* d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1659 * Our various file operations. abfa3df3 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-11 1660 */ d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1661 static int mcam_v4l_open(struct file *filp) d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1662 { d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1663 struct mcam_camera *cam = video_drvdata(filp); 949bd408 drivers/media/platform/marvell-ccic/mcam-core.c Hans Verkuil 2015-03-05 1664 int ret; abfa3df3 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-11 1665 d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1666 mutex_lock(&cam->s_mutex); 949bd408 drivers/media/platform/marvell-ccic/mcam-core.c Hans Verkuil 2015-03-05 1667 ret = v4l2_fh_open(filp); d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1668 if (ret) d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1669 goto out; 949bd408 drivers/media/platform/marvell-ccic/mcam-core.c Hans Verkuil 2015-03-05 1670 if (v4l2_fh_is_singular_file(filp)) { a4f7d692 drivers/media/platform/marvell-ccic/mcam-core.c Lubomir Rintel 2018-11-05 1671 ret = sensor_call(cam, core, s_power, 1); 05fed816 drivers/media/platform/marvell-ccic/mcam-core.c Libin Yang 2013-07-03 1672 if (ret) a4f7d692 drivers/media/platform/marvell-ccic/mcam-core.c Lubomir Rintel 2018-11-05 1673 return ret; ^^^^^^^^^^ This should be a goto out; a4f7d692 drivers/media/platform/marvell-ccic/mcam-core.c Lubomir Rintel 2018-11-05 1674 mcam_clk_enable(cam); d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1675 __mcam_cam_reset(cam); d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1676 mcam_set_config_needed(cam, 1); d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1677 } d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1678 out: d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 1679 mutex_unlock(&cam->s_mutex); 44fbcb10 drivers/media/platform/marvell-ccic/mcam-core.c Hans Verkuil 2015-03-05 1680 if (ret) 44fbcb10 drivers/media/platform/marvell-ccic/mcam-core.c Hans Verkuil 2015-03-05 1681 v4l2_fh_release(filp); d43dae75 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-07-08 @1682 return ret; a9b36e85 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-20 1683 } abfa3df3 drivers/media/video/marvell-ccic/mcam-core.c Jonathan Corbet 2011-06-11 1684 :::::: The code at line 1682 was first introduced by commit :::::: d43dae75cc1140bf27a59aa6d8e8bc7a00f009cc [media] marvell-cam: core code reorganization :::::: TO: Jonathan Corbet <corbet@lwn.net> :::::: CC: Mauro Carvalho Chehab <mchehab@redhat.com> --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index 0164afc405d1..0e712bb941ba 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c @@ -33,6 +33,7 @@ #include <linux/wait.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/clkdev.h> #include "mcam-core.h" @@ -533,11 +534,10 @@ static int cafe_pci_probe(struct pci_dev *pdev, goto out_iounmap; /* - * Initialize the controller and leave it powered up. It will - * stay that way until the sensor driver shows up. + * Initialize the controller. */ cafe_ctlr_init(mcam); - cafe_ctlr_power_up(mcam); + /* * Set up I2C/SMBUS communications. We have to drop the mutex here * because the sensor could attach in this call chain, leading to @@ -555,12 +555,15 @@ static int cafe_pci_probe(struct pci_dev *pdev, if (ret) goto out_smbus_shutdown; + clkdev_create(mcam->mclk, "xclk", "%d-%04x", + i2c_adapter_id(cam->i2c_adapter), ov7670_info.addr); + if (i2c_new_device(cam->i2c_adapter, &ov7670_info)) { cam->registered = 1; return 0; } - cafe_shutdown(cam); + mccic_shutdown(mcam); out_smbus_shutdown: cafe_smbus_shutdown(cam); out_pdown: diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 87812b7287f0..4656eaee2f29 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -22,6 +22,7 @@ #include <linux/vmalloc.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> @@ -303,9 +304,6 @@ static void mcam_enable_mipi(struct mcam_camera *mcam) */ mcam_reg_write(mcam, REG_CSI2_CTRL0, CSI2_C0_MIPI_EN | CSI2_C0_ACT_LANE(mcam->lane)); - mcam_reg_write(mcam, REG_CLKCTRL, - (mcam->mclk_src << 29) | mcam->mclk_div); - mcam->mipi_enabled = true; } } @@ -846,11 +844,6 @@ static void mcam_ctlr_init(struct mcam_camera *cam) * but it's good to be sure. */ mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE); - /* - * Clock the sensor appropriately. Controller clock should - * be 48MHz, sensor "typical" value is half that. - */ - mcam_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK); spin_unlock_irqrestore(&cam->dev_lock, flags); } @@ -898,14 +891,15 @@ static int mcam_ctlr_power_up(struct mcam_camera *cam) int ret; spin_lock_irqsave(&cam->dev_lock, flags); - ret = cam->plat_power_up(cam); - if (ret) { - spin_unlock_irqrestore(&cam->dev_lock, flags); - return ret; + if (cam->plat_power_up) { + ret = cam->plat_power_up(cam); + if (ret) { + spin_unlock_irqrestore(&cam->dev_lock, flags); + return ret; + } } mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN); spin_unlock_irqrestore(&cam->dev_lock, flags); - msleep(5); /* Just to be sure */ return 0; } @@ -920,10 +914,101 @@ static void mcam_ctlr_power_down(struct mcam_camera *cam) * power down routine. */ mcam_reg_set_bit(cam, REG_CTRL1, C1_PWRDWN); - cam->plat_power_down(cam); + if (cam->plat_power_down) + cam->plat_power_down(cam); spin_unlock_irqrestore(&cam->dev_lock, flags); } +/* ---------------------------------------------------------------------- */ +/* + * Controller clocks. + */ +static void mcam_clk_enable(struct mcam_camera *mcam) +{ + unsigned int i; + + for (i = 0; i < NR_MCAM_CLK; i++) { + if (!IS_ERR(mcam->clk[i])) + clk_prepare_enable(mcam->clk[i]); + } +} + +static void mcam_clk_disable(struct mcam_camera *mcam) +{ + int i; + + for (i = NR_MCAM_CLK - 1; i >= 0; i--) { + if (!IS_ERR(mcam->clk[i])) + clk_disable_unprepare(mcam->clk[i]); + } +} + +/* ---------------------------------------------------------------------- */ +/* + * Master sensor clock. + */ +static int mclk_prepare(struct clk_hw *hw) +{ + struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw); + + clk_prepare(cam->clk[0]); + return 0; +} + +static void mclk_unprepare(struct clk_hw *hw) +{ + struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw); + + clk_unprepare(cam->clk[0]); +} + +static int mclk_enable(struct clk_hw *hw) +{ + struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw); + int mclk_src; + int mclk_div; + + /* + * Clock the sensor appropriately. Controller clock should + * be 48MHz, sensor "typical" value is half that. + */ + if (cam->bus_type == V4L2_MBUS_CSI2_DPHY) { + mclk_src = cam->mclk_src; + mclk_div = cam->mclk_div; + } else { + mclk_src = 3; + mclk_div = 2; + } + + clk_enable(cam->clk[0]); + mcam_reg_write(cam, REG_CLKCTRL, (mclk_src << 29) | mclk_div); + mcam_ctlr_power_up(cam); + + return 0; +} + +static void mclk_disable(struct clk_hw *hw) +{ + struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw); + + mcam_ctlr_power_down(cam); + clk_disable(cam->clk[0]); +} + +static unsigned long mclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return 48000000; +} + +static const struct clk_ops mclk_ops = { + .prepare = mclk_prepare, + .unprepare = mclk_unprepare, + .enable = mclk_enable, + .disable = mclk_disable, + .recalc_rate = mclk_recalc_rate, +}; + /* -------------------------------------------------------------------- */ /* * Communications with the sensor. @@ -948,7 +1033,6 @@ static int mcam_cam_init(struct mcam_camera *cam) ret = __mcam_cam_reset(cam); /* Get/set parameters? */ cam->state = S_IDLE; - mcam_ctlr_power_down(cam); return ret; } @@ -1584,9 +1668,10 @@ static int mcam_v4l_open(struct file *filp) if (ret) goto out; if (v4l2_fh_is_singular_file(filp)) { - ret = mcam_ctlr_power_up(cam); + ret = sensor_call(cam, core, s_power, 1); if (ret) - goto out; + return ret; + mcam_clk_enable(cam); __mcam_cam_reset(cam); mcam_set_config_needed(cam, 1); } @@ -1608,7 +1693,8 @@ static int mcam_v4l_release(struct file *filp) _vb2_fop_release(filp, NULL); if (last_open) { mcam_disable_mipi(cam); - mcam_ctlr_power_down(cam); + sensor_call(cam, core, s_power, 0); + mcam_clk_disable(cam); if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read) mcam_free_dma_bufs(cam); } @@ -1806,6 +1892,7 @@ static const struct v4l2_async_notifier_operations mccic_notify_ops = { int mccic_register(struct mcam_camera *cam) { + struct clk_init_data mclk_init = { }; int ret; /* @@ -1838,7 +1925,10 @@ int mccic_register(struct mcam_camera *cam) mcam_set_config_needed(cam, 1); cam->pix_format = mcam_def_pix_format; cam->mbus_code = mcam_def_mbus_code; - mcam_ctlr_init(cam); + + mcam_clk_enable(cam); + mcam_ctlr_init(cam); // XXX? + mcam_clk_disable(cam); /* * Register sensor notifier. @@ -1857,6 +1947,26 @@ int mccic_register(struct mcam_camera *cam) goto out; } + /* + * Register sensor master clock. + */ + mclk_init.parent_names = NULL; + mclk_init.num_parents = 0; + mclk_init.ops = &mclk_ops; + mclk_init.name = "mclk"; + + of_property_read_string(cam->dev->of_node, "clock-output-names", + &mclk_init.name); + + cam->mclk_hw.init = &mclk_init; + + cam->mclk = devm_clk_register(cam->dev, &cam->mclk_hw); + if (IS_ERR(cam->mclk)) { + ret = PTR_ERR(cam->mclk); + dev_err(cam->dev, "can't register clock\n"); + goto out; + } + /* * If so requested, try to get our DMA buffers now. */ @@ -1884,7 +1994,7 @@ void mccic_shutdown(struct mcam_camera *cam) */ if (!list_empty(&cam->vdev.fh_list)) { cam_warn(cam, "Removing a device with users!\n"); - mcam_ctlr_power_down(cam); + sensor_call(cam, core, s_power, 0); } if (cam->buffer_mode == B_vmalloc) mcam_free_dma_bufs(cam); @@ -1906,7 +2016,8 @@ void mccic_suspend(struct mcam_camera *cam) enum mcam_state cstate = cam->state; mcam_ctlr_stop_dma(cam); - mcam_ctlr_power_down(cam); + sensor_call(cam, core, s_power, 0); + mcam_clk_disable(cam); cam->state = cstate; } mutex_unlock(&cam->s_mutex); @@ -1919,14 +2030,15 @@ int mccic_resume(struct mcam_camera *cam) mutex_lock(&cam->s_mutex); if (!list_empty(&cam->vdev.fh_list)) { - ret = mcam_ctlr_power_up(cam); + mcam_clk_enable(cam); + ret = sensor_call(cam, core, s_power, 1); if (ret) { mutex_unlock(&cam->s_mutex); return ret; } __mcam_cam_reset(cam); } else { - mcam_ctlr_power_down(cam); + sensor_call(cam, core, s_power, 0); } mutex_unlock(&cam->s_mutex); diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 4a72213aca1a..2e3a7567a76a 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h @@ -8,6 +8,7 @@ #define _MCAM_CORE_H #include <linux/list.h> +#include <linux/clk-provider.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-dev.h> @@ -125,6 +126,8 @@ struct mcam_camera { /* clock tree support */ struct clk *clk[NR_MCAM_CLK]; + struct clk_hw mclk_hw; + struct clk *mclk; /* * Callbacks from the core to the platform code. diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index cafb55f2b057..787984193ffe 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -22,9 +22,7 @@ #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> -#include <linux/gpio.h> #include <linux/io.h> -#include <linux/delay.h> #include <linux/list.h> #include <linux/pm.h> #include <linux/clk.h> @@ -38,7 +36,6 @@ MODULE_LICENSE("GPL"); static char *mcam_clks[] = {"CCICAXICLK", "CCICFUNCLK", "CCICPHYCLK"}; struct mmp_camera { - void __iomem *power_regs; struct platform_device *pdev; struct mcam_camera mcam; struct list_head devlist; @@ -94,95 +91,6 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev) return NULL; } - - - -/* - * Power-related registers; this almost certainly belongs - * somewhere else. - * - * ARMADA 610 register manual, sec 7.2.1, p1842. - */ -#define CPU_SUBSYS_PMU_BASE 0xd4282800 -#define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */ -#define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */ -#define REG_CCIC2_CRCR 0xf4 /* CCIC2 clk reset ctrl reg */ - -static void mcam_clk_enable(struct mcam_camera *mcam) -{ - unsigned int i; - - for (i = 0; i < NR_MCAM_CLK; i++) { - if (!IS_ERR(mcam->clk[i])) - clk_prepare_enable(mcam->clk[i]); - } -} - -static void mcam_clk_disable(struct mcam_camera *mcam) -{ - int i; - - for (i = NR_MCAM_CLK - 1; i >= 0; i--) { - if (!IS_ERR(mcam->clk[i])) - clk_disable_unprepare(mcam->clk[i]); - } -} - -/* - * Power control. - */ -static void mmpcam_power_up_ctlr(struct mmp_camera *cam) -{ - iowrite32(0x3f, cam->power_regs + REG_CCIC_DCGCR); - iowrite32(0x3805b, cam->power_regs + REG_CCIC_CRCR); - mdelay(1); -} - -static int mmpcam_power_up(struct mcam_camera *mcam) -{ - struct mmp_camera *cam = mcam_to_cam(mcam); - struct mmp_camera_platform_data *pdata; - -/* - * Turn on power and clocks to the controller. - */ - mmpcam_power_up_ctlr(cam); - mcam_clk_enable(mcam); -/* - * Provide power to the sensor. - */ - mcam_reg_write(mcam, REG_CLKCTRL, 0x60000002); - pdata = cam->pdev->dev.platform_data; - gpio_set_value(pdata->sensor_power_gpio, 1); - mdelay(5); - mcam_reg_clear_bit(mcam, REG_CTRL1, 0x10000000); - gpio_set_value(pdata->sensor_reset_gpio, 0); /* reset is active low */ - mdelay(5); - gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */ - mdelay(5); - - return 0; -} - -static void mmpcam_power_down(struct mcam_camera *mcam) -{ - struct mmp_camera *cam = mcam_to_cam(mcam); - struct mmp_camera_platform_data *pdata; -/* - * Turn off clocks and set reset lines - */ - iowrite32(0, cam->power_regs + REG_CCIC_DCGCR); - iowrite32(0, cam->power_regs + REG_CCIC_CRCR); -/* - * Shut down the sensor. - */ - pdata = cam->pdev->dev.platform_data; - gpio_set_value(pdata->sensor_power_gpio, 0); - gpio_set_value(pdata->sensor_reset_gpio, 0); - - mcam_clk_disable(mcam); -} - /* * calc the dphy register values * There are three dphy registers being used. @@ -328,8 +236,6 @@ static int mmpcam_probe(struct platform_device *pdev) INIT_LIST_HEAD(&cam->devlist); mcam = &cam->mcam; - mcam->plat_power_up = mmpcam_power_up; - mcam->plat_power_down = mmpcam_power_down; mcam->calc_dphy = mmpcam_calc_dphy; mcam->dev = &pdev->dev; pdata = pdev->dev.platform_data; @@ -367,33 +273,6 @@ static int mmpcam_probe(struct platform_device *pdev) if (IS_ERR(mcam->regs)) return PTR_ERR(mcam->regs); mcam->regs_size = resource_size(res); - /* - * Power/clock memory is elsewhere; get it too. Perhaps this - * should really be managed outside of this driver? - */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - cam->power_regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(cam->power_regs)) - return PTR_ERR(cam->power_regs); - /* - * Sensor GPIO pins. - */ - ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio, - "cam-power"); - if (ret) { - dev_err(&pdev->dev, "Can't get sensor power gpio %d", - pdata->sensor_power_gpio); - return ret; - } - gpio_direction_output(pdata->sensor_power_gpio, 0); - ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio, - "cam-reset"); - if (ret) { - dev_err(&pdev->dev, "Can't get sensor reset gpio %d", - pdata->sensor_reset_gpio); - return ret; - } - gpio_direction_output(pdata->sensor_reset_gpio, 0); mcam_init_clk(mcam); @@ -411,14 +290,21 @@ static int mmpcam_probe(struct platform_device *pdev) fwnode_handle_put(ep); /* - * Power the device up and hand it off to the core. + * Register the device with the core. */ - ret = mmpcam_power_up(mcam); - if (ret) - return ret; ret = mccic_register(mcam); if (ret) - goto out_power_down; + return ret; + + /* + * Add OF clock provider. + */ + ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, + mcam->mclk); + if (ret) { + dev_err(&pdev->dev, "can't add DT clock provider\n"); + goto out; + } /* * Finally, set up our IRQ now that the core is ready to @@ -427,7 +313,7 @@ static int mmpcam_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { ret = -ENODEV; - goto out_unregister; + goto out; } cam->irq = res->start; ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED, @@ -437,10 +323,10 @@ static int mmpcam_probe(struct platform_device *pdev) return 0; } -out_unregister: +out: + fwnode_handle_put(mcam->asd.match.fwnode); mccic_shutdown(mcam); -out_power_down: - mmpcam_power_down(mcam); + return ret; } @@ -451,7 +337,6 @@ static int mmpcam_remove(struct mmp_camera *cam) mmpcam_remove_device(cam); mccic_shutdown(mcam); - mmpcam_power_down(mcam); return 0; } @@ -483,12 +368,6 @@ static int mmpcam_resume(struct platform_device *pdev) { struct mmp_camera *cam = mmpcam_find_device(pdev); - /* - * Power up unconditionally just in case the core tries to - * touch a register even if nothing was active before; trust - * me, it's better this way. - */ - mmpcam_power_up_ctlr(cam); return mccic_resume(&cam->mcam); } diff --git a/include/linux/platform_data/media/mmp-camera.h b/include/linux/platform_data/media/mmp-camera.h index c573ebc40035..53adaab64f28 100644 --- a/include/linux/platform_data/media/mmp-camera.h +++ b/include/linux/platform_data/media/mmp-camera.h @@ -12,8 +12,6 @@ enum dphy3_algo { }; struct mmp_camera_platform_data { - int sensor_power_gpio; - int sensor_reset_gpio; enum v4l2_mbus_type bus_type; int mclk_src; /* which clock source the MCLK derives from */ int mclk_div; /* Clock Divider Value for MCLK */
The sensor needs the MCLK clock running when it's being probed. On platforms where the sensor is instantiated from a DT (MMP2) it is going to happen asynchronously. Therefore, the current modus operandi, where the bridge driver fiddles with the sensor power and clock itself is not going to fly. As the comments wisely note, this doesn't even belong there. Luckily, the ov7670 driver is already able to control its power and reset lines, we can just drop the MMP platform glue altogether. It also requests the clock via the standard clock subsystem. Good -- let's set up a clock instance so that the sensor can ask us to enable the clock. Note that this is pretty dumb at the moment: the clock is hardwired to a particular frequency and parent. It was always the case. Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> --- .../media/platform/marvell-ccic/cafe-driver.c | 11 +- .../media/platform/marvell-ccic/mcam-core.c | 158 +++++++++++++++--- .../media/platform/marvell-ccic/mcam-core.h | 3 + .../media/platform/marvell-ccic/mmp-driver.c | 153 ++--------------- .../linux/platform_data/media/mmp-camera.h | 2 - 5 files changed, 161 insertions(+), 166 deletions(-)