diff options
-rw-r--r-- | Documentation/admin-guide/media/i2c-cardlist.rst | 1 | ||||
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | drivers/media/i2c/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/i2c/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/Kconfig | 8 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/Makefile | 4 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols.h | 349 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_capture.c | 158 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_controls.c | 625 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_core.c | 1051 | ||||
-rw-r--r-- | drivers/media/i2c/m5mols/m5mols_reg.h | 359 | ||||
-rw-r--r-- | include/media/i2c/m5mols.h | 25 |
12 files changed, 0 insertions, 2590 deletions
diff --git a/Documentation/admin-guide/media/i2c-cardlist.rst b/Documentation/admin-guide/media/i2c-cardlist.rst index 4819d9aa55f1..26827f4b4a3d 100644 --- a/Documentation/admin-guide/media/i2c-cardlist.rst +++ b/Documentation/admin-guide/media/i2c-cardlist.rst @@ -72,7 +72,6 @@ imx319 Sony IMX319 sensor imx334 Sony IMX334 sensor imx355 Sony IMX355 sensor imx412 Sony IMX412 sensor -m5mols Fujitsu M-5MOLS 8MP sensor mt9m001 mt9m001 mt9m032 MT9M032 camera sensor mt9m111 mt9m111, mt9m112 and mt9m131 diff --git a/MAINTAINERS b/MAINTAINERS index 8b475bf063f6..0dfc8f3e4e2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8411,14 +8411,6 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/fujitsu-laptop.c -FUJITSU M-5MO LS CAMERA ISP DRIVER -M: Kyungmin Park <kyungmin.park@samsung.com> -M: Heungjun Kim <riverful.kim@samsung.com> -L: linux-media@vger.kernel.org -S: Maintained -F: drivers/media/i2c/m5mols/ -F: include/media/i2c/m5mols.h - FUJITSU TABLET EXTRAS M: Robert Gerlach <khnz@gmx.de> L: platform-driver-x86@vger.kernel.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index c369db886b40..5be28ca5b5b2 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -848,7 +848,6 @@ config VIDEO_VS6624 source "drivers/media/i2c/ccs/Kconfig" source "drivers/media/i2c/et8ek8/Kconfig" -source "drivers/media/i2c/m5mols/Kconfig" endmenu diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 77052f941fec..f739b639b429 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -55,7 +55,6 @@ obj-$(CONFIG_VIDEO_KS0127) += ks0127.o obj-$(CONFIG_VIDEO_LM3560) += lm3560.o obj-$(CONFIG_VIDEO_LM3646) += lm3646.o obj-$(CONFIG_VIDEO_M52790) += m52790.o -obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o obj-$(CONFIG_VIDEO_MAX9286) += max9286.o obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o diff --git a/drivers/media/i2c/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig deleted file mode 100644 index 7f0af32f4376..000000000000 --- a/drivers/media/i2c/m5mols/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config VIDEO_M5MOLS - tristate "Fujitsu M-5MOLS 8MP sensor support" - depends on I2C && VIDEO_DEV - select MEDIA_CONTROLLER - select VIDEO_V4L2_SUBDEV_API - help - This driver supports Fujitsu M-5MOLS camera sensor with ISP diff --git a/drivers/media/i2c/m5mols/Makefile b/drivers/media/i2c/m5mols/Makefile deleted file mode 100644 index 13fa8ec29ac0..000000000000 --- a/drivers/media/i2c/m5mols/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o - -obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o diff --git a/drivers/media/i2c/m5mols/m5mols.h b/drivers/media/i2c/m5mols/m5mols.h deleted file mode 100644 index d8545d2280af..000000000000 --- a/drivers/media/i2c/m5mols/m5mols.h +++ /dev/null @@ -1,349 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Header for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim <riverful.kim@samsung.com> - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com> - */ - -#ifndef M5MOLS_H -#define M5MOLS_H - -#include <linux/sizes.h> -#include <linux/gpio/consumer.h> -#include <media/v4l2-subdev.h> -#include "m5mols_reg.h" - - -/* An amount of data transmitted in addition to the value - * determined by CAPP_JPEG_SIZE_MAX register. - */ -#define M5MOLS_JPEG_TAGS_SIZE 0x20000 -#define M5MOLS_MAIN_JPEG_SIZE_MAX (5 * SZ_1M) - -extern int m5mols_debug; - -enum m5mols_restype { - M5MOLS_RESTYPE_MONITOR, - M5MOLS_RESTYPE_CAPTURE, - M5MOLS_RESTYPE_MAX, -}; - -/** - * struct m5mols_resolution - structure for the resolution - * @type: resolution type according to the pixel code - * @width: width of the resolution - * @height: height of the resolution - * @reg: resolution preset register value - */ -struct m5mols_resolution { - u8 reg; - enum m5mols_restype type; - u16 width; - u16 height; -}; - -/** - * struct m5mols_exif - structure for the EXIF information of M-5MOLS - * @exposure_time: exposure time register value - * @shutter_speed: speed of the shutter register value - * @aperture: aperture register value - * @brightness: brightness register value - * @exposure_bias: it calls also EV bias - * @iso_speed: ISO register value - * @flash: status register value of the flash - * @sdr: status register value of the Subject Distance Range - * @qval: not written exact meaning in document - */ -struct m5mols_exif { - u32 exposure_time; - u32 shutter_speed; - u32 aperture; - u32 brightness; - u32 exposure_bias; - u16 iso_speed; - u16 flash; - u16 sdr; - u16 qval; -}; - -/** - * struct m5mols_capture - Structure for the capture capability - * @exif: EXIF information - * @buf_size: internal JPEG frame buffer size, in bytes - * @main: size in bytes of the main image - * @thumb: size in bytes of the thumb image, if it was accompanied - * @total: total size in bytes of the produced image - */ -struct m5mols_capture { - struct m5mols_exif exif; - unsigned int buf_size; - u32 main; - u32 thumb; - u32 total; -}; - -/** - * struct m5mols_scenemode - structure for the scenemode capability - * @metering: metering light register value - * @ev_bias: EV bias register value - * @wb_mode: mode which means the WhiteBalance is Auto or Manual - * @wb_preset: whitebalance preset register value in the Manual mode - * @chroma_en: register value whether the Chroma capability is enabled or not - * @chroma_lvl: chroma's level register value - * @edge_en: register value Whether the Edge capability is enabled or not - * @edge_lvl: edge's level register value - * @af_range: Auto Focus's range - * @fd_mode: Face Detection mode - * @mcc: Multi-axis Color Conversion which means emotion color - * @light: status of the Light - * @flash: status of the Flash - * @tone: Tone color which means Contrast - * @iso: ISO register value - * @capt_mode: Mode of the Image Stabilization while the camera capturing - * @wdr: Wide Dynamic Range register value - * - * The each value according to each scenemode is recommended in the documents. - */ -struct m5mols_scenemode { - u8 metering; - u8 ev_bias; - u8 wb_mode; - u8 wb_preset; - u8 chroma_en; - u8 chroma_lvl; - u8 edge_en; - u8 edge_lvl; - u8 af_range; - u8 fd_mode; - u8 mcc; - u8 light; - u8 flash; - u8 tone; - u8 iso; - u8 capt_mode; - u8 wdr; -}; - -#define VERSION_STRING_SIZE 22 - -/** - * struct m5mols_version - firmware version information - * @customer: customer information - * @project: version of project information according to customer - * @fw: firmware revision - * @hw: hardware revision - * @param: version of the parameter - * @awb: Auto WhiteBalance algorithm version - * @str: information about manufacturer and packaging vendor - * @af: Auto Focus version - * - * The register offset starts the customer version at 0x0, and it ends - * the awb version at 0x09. The customer, project information occupies 1 bytes - * each. And also the fw, hw, param, awb each requires 2 bytes. The str is - * unique string associated with firmware's version. It includes information - * about manufacturer and the vendor of the sensor's packaging. The least - * significant 2 bytes of the string indicate packaging manufacturer. - */ -struct m5mols_version { - u8 customer; - u8 project; - u16 fw; - u16 hw; - u16 param; - u16 awb; - u8 str[VERSION_STRING_SIZE]; - u8 af; -}; - -/** - * struct m5mols_info - M-5MOLS driver data structure - * @pdata: platform data - * @sd: v4l-subdev instance - * @pad: media pad - * @irq_waitq: waitqueue for the capture - * @irq_done: set to 1 in the interrupt handler - * @handle: control handler - * @auto_exposure: auto/manual exposure control - * @exposure_bias: exposure compensation control - * @exposure: manual exposure control - * @metering: exposure metering control - * @auto_iso: auto/manual ISO sensitivity control - * @iso: manual ISO sensitivity control - * @auto_wb: auto white balance control - * @lock_3a: 3A lock control - * @colorfx: color effect control - * @saturation: saturation control - * @zoom: zoom control - * @wdr: wide dynamic range control - * @stabilization: image stabilization control - * @jpeg_quality: JPEG compression quality control - * @set_power: optional power callback to the board code - * @reset: GPIO driving the reset pin of M-5MOLS - * @lock: mutex protecting the structure fields below - * @ffmt: current fmt according to resolution type - * @res_type: current resolution type - * @ver: information of the version - * @cap: the capture mode attributes - * @isp_ready: 1 when the ISP controller has completed booting - * @power: current sensor's power status - * @ctrl_sync: 1 when the control handler state is restored in H/W - * @resolution: register value for current resolution - * @mode: register value for current operation mode - */ -struct m5mols_info { - const struct m5mols_platform_data *pdata; - struct v4l2_subdev sd; - struct media_pad pad; - - wait_queue_head_t irq_waitq; - atomic_t irq_done; - - struct v4l2_ctrl_handler handle; - struct { - /* exposure/exposure bias/auto exposure cluster */ - struct v4l2_ctrl *auto_exposure; - struct v4l2_ctrl *exposure_bias; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *metering; - }; - struct { - /* iso/auto iso cluster */ - struct v4l2_ctrl *auto_iso; - struct v4l2_ctrl *iso; - }; - struct v4l2_ctrl *auto_wb; - - struct v4l2_ctrl *lock_3a; - struct v4l2_ctrl *colorfx; - struct v4l2_ctrl *saturation; - struct v4l2_ctrl *zoom; - struct v4l2_ctrl *wdr; - struct v4l2_ctrl *stabilization; - struct v4l2_ctrl *jpeg_quality; - - int (*set_power)(struct device *dev, int on); - struct gpio_desc *reset; - - struct mutex lock; - - struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; - int res_type; - - struct m5mols_version ver; - struct m5mols_capture cap; - - unsigned int isp_ready:1; - unsigned int power:1; - unsigned int ctrl_sync:1; - - u8 resolution; - u8 mode; -}; - -#define is_available_af(__info) (__info->ver.af) -#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) -#define is_manufacturer(__info, __manufacturer) \ - (__info->ver.str[0] == __manufacturer[0] && \ - __info->ver.str[1] == __manufacturer[1]) -/* - * I2C operation of the M-5MOLS - * - * The I2C read operation of the M-5MOLS requires 2 messages. The first - * message sends the information about the command, command category, and total - * message size. The second message is used to retrieve the data specified in - * the first message - * - * 1st message 2nd message - * +-------+---+----------+-----+-------+ +------+------+------+------+ - * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] | - * +-------+---+----------+-----+-------+ +------+------+------+------+ - * - size1: message data size(5 in this case) - * - size2: desired buffer size of the 2nd message - * - d[0..3]: according to size2 - * - * The I2C write operation needs just one message. The message includes - * category, command, total size, and desired data. - * - * 1st message - * +-------+---+----------+-----+------+------+------+------+ - * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] | - * +-------+---+----------+-----+------+------+------+------+ - * - d[0..3]: according to size1 - */ -int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val); -int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); -int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); -int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); - -int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask, - int timeout); - -/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */ -#define M5MOLS_I2C_RDY_WAIT_FL (1 << 16) -/* ISP state transition timeout, in ms */ -#define M5MOLS_MODE_CHANGE_TIMEOUT 200 -#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250 - -/* - * Mode operation of the M-5MOLS - * - * Changing the mode of the M-5MOLS is needed right executing order. - * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed - * by user. There are various categories associated with each mode. - * - * +============================================================+ - * | mode | category | - * +============================================================+ - * | FLASH | FLASH(only after Stand-by or Power-on) | - * | SYSTEM | SYSTEM(only after sensor arm-booting) | - * | PARAMETER | PARAMETER | - * | MONITOR | MONITOR(preview), Auto Focus, Face Detection | - * | CAPTURE | Single CAPTURE, Preview(recording) | - * +============================================================+ - * - * The available executing order between each modes are as follows: - * PARAMETER <---> MONITOR <---> CAPTURE - */ -int m5mols_set_mode(struct m5mols_info *info, u8 mode); - -int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg); -int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout); -int m5mols_restore_controls(struct m5mols_info *info); -int m5mols_start_capture(struct m5mols_info *info); -int m5mols_do_scenemode(struct m5mols_info *info, u8 mode); -int m5mols_lock_3a(struct m5mols_info *info, bool lock); -int m5mols_set_ctrl(struct v4l2_ctrl *ctrl); -int m5mols_init_controls(struct v4l2_subdev *sd); - -/* The firmware function */ -int m5mols_update_fw(struct v4l2_subdev *sd, - int (*set_power)(struct m5mols_info *, bool)); - -static inline struct m5mols_info *to_m5mols(struct v4l2_subdev *subdev) -{ - return container_of(subdev, struct m5mols_info, sd); -} - -static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -{ - struct m5mols_info *info = container_of(ctrl->handler, - struct m5mols_info, handle); - return &info->sd; -} - -static inline void m5mols_set_ctrl_mode(struct v4l2_ctrl *ctrl, - unsigned int mode) -{ - ctrl->priv = (void *)(uintptr_t)mode; -} - -static inline unsigned int m5mols_get_ctrl_mode(struct v4l2_ctrl *ctrl) -{ - return (unsigned int)(uintptr_t)ctrl->priv; -} - -#endif /* M5MOLS_H */ diff --git a/drivers/media/i2c/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c deleted file mode 100644 index 275c5b2539fd..000000000000 --- a/drivers/media/i2c/m5mols/m5mols_capture.c +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -/* - * The Capture code for Fujitsu M-5MOLS ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim <riverful.kim@samsung.com> - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com> - */ - -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/regulator/consumer.h> -#include <linux/videodev2.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-subdev.h> -#include <media/i2c/m5mols.h> -#include <media/drv-intf/exynos-fimc.h> - -#include "m5mols.h" -#include "m5mols_reg.h" - -/** - * m5mols_read_rational - I2C read of a rational number - * @sd: sub-device, as pointed by struct v4l2_subdev - * @addr_num: numerator register - * @addr_den: denominator register - * @val: place to store the division result - * - * Read numerator and denominator from registers @addr_num and @addr_den - * respectively and return the division result in @val. - */ -static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, - u32 addr_den, u32 *val) -{ - u32 num, den; - - int ret = m5mols_read_u32(sd, addr_num, &num); - if (!ret) - ret = m5mols_read_u32(sd, addr_den, &den); - if (ret) - return ret; - *val = den == 0 ? 0 : num / den; - return ret; -} - -/** - * m5mols_capture_info - Gather captured image information - * @info: M-5MOLS driver data structure - * - * For now it gathers only EXIF information and file size. - */ -static int m5mols_capture_info(struct m5mols_info *info) -{ - struct m5mols_exif *exif = &info->cap.exif; - struct v4l2_subdev *sd = &info->sd; - int ret; - - ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU, - EXIF_INFO_EXPTIME_DE, &exif->exposure_time); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE, - &exif->shutter_speed); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE, - &exif->aperture); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE, - &exif->brightness); - if (ret) - return ret; - ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE, - &exif->exposure_bias); - if (ret) - return ret; - - ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed); - if (!ret) - ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash); - if (!ret) - ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr); - if (!ret) - ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval); - if (ret) - return ret; - - if (!ret) - ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main); - if (!ret) - ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb); - if (!ret) - info->cap.total = info->cap.main + info->cap.thumb; - - return ret; -} - -int m5mols_start_capture(struct m5mols_info *info) -{ - unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE; - struct v4l2_subdev *sd = &info->sd; - int ret; - - /* - * Synchronize the controls, set the capture frame resolution and color - * format. The frame capture is initiated during switching from Monitor - * to Capture mode. - */ - ret = m5mols_set_mode(info, REG_MONITOR); - if (!ret) - ret = m5mols_restore_controls(info); - if (!ret) - ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); - if (!ret) - ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution); - if (!ret) - ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize); - if (!ret) - ret = m5mols_set_mode(info, REG_CAPTURE); - if (!ret) - /* Wait until a frame is captured to ISP internal memory */ - ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); - if (ret) - return ret; - - /* - * Initiate the captured data transfer to a MIPI-CSI receiver. - */ - ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); - if (!ret) - ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); - if (!ret) { - bool captured = false; - unsigned int size; - - /* Wait for the capture completion interrupt */ - ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); - if (!ret) { - captured = true; - ret = m5mols_capture_info(info); - } - size = captured ? info->cap.main : 0; - v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n", - __func__, size, info->cap.thumb); - - v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size); - } - - return ret; -} diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c deleted file mode 100644 index b45e0e08b6c8..000000000000 --- a/drivers/media/i2c/m5mols/m5mols_controls.c +++ /dev/null @@ -1,625 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Controls for M-5MOLS 8M Pixel camera sensor with ISP - * - * Copyright (C) 2011 Samsung Electronics Co., Ltd. - * Author: HeungJun Kim <riverful.kim@samsung.com> - * - * Copyright (C) 2009 Samsung Electronics Co., Ltd. - * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com> - */ - -#include <linux/i2c.h> -#include <linux/delay.h> -#include <linux/videodev2.h> -#include <media/v4l2-ctrls.h> - -#include "m5mols.h" -#include "m5mols_reg.h" - -static struct m5mols_scenemode m5mols_default_scenemode[] = { - [REG_SCENE_NORMAL] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF, - 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_PORTRAIT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 4, - REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_LANDSCAPE] = { - REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 4, REG_EDGE_ON, 6, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_SPORTS] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_PARTY_INDOOR] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 4, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_BEACH_SNOW] = { - REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 4, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_SUNSET] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, - REG_AWB_DAYLIGHT, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_DAWN_DUSK] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, - REG_AWB_FLUORESCENT_1, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_FALL] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 5, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_NIGHT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_AGAINST_LIGHT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_FIRE] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, - }, - [REG_SCENE_TEXT] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 7, - REG_AF_MACRO, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON, - }, - [REG_SCENE_CANDLE] = { - REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, - REG_CHROMA_ON, 3, REG_EDGE_ON, 5, - REG_AF_NORMAL, REG_FD_OFF, - REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, - 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, - }, -}; - -/** - * m5mols_do_scenemode() - Change current scenemode - * @info: M-5MOLS driver data structure - * @mode: Desired mode of the scenemode - * - * WARNING: The execution order is important. Do not change the order. - */ -int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) -{ - struct v4l2_subdev *sd = &info->sd; - struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; - int ret; - - if (mode > REG_SCENE_CANDLE) - return -EINVAL; - - ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0); - if (!ret) - ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); - if (!ret) - ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode); - if (!ret) - ret = m5mols_write(sd, AE_MODE, scenemode.metering); - if (!ret) - ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias); - if (!ret) - ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode); - if (!ret) - ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset); - if (!ret) - ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en); - if (!ret) - ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl); - if (!ret) - ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en); - if (!ret) - ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl); - if (!ret && is_available_af(info)) - ret = m5mols_write(sd, AF_MODE, scenemode.af_range); - if (!ret && is_available_af(info)) - ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode); - if (!ret) - ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone); - if (!ret) - ret = m5mols_write(sd, AE_ISO, scenemode.iso); - if (!ret) - ret = m5mols_set_mode(info, REG_CAPTURE); - if (!ret) - ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); - if (!ret) - ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc); - if (!ret) - ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light); - if (!ret) - ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash); - if (!ret) - ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); - if (!ret) - ret = m5mols_set_mode(info, REG_MONITOR); - - return ret; -} - -static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl) -{ - bool af_lock = ctrl->val & V4L2_LOCK_FOCUS; - int ret = 0; - - if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) { - bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE; - - ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ? - REG_AE_LOCK : REG_AE_UNLOCK); - if (ret) - return ret; - } - - if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE) - && info->auto_wb->val) { - bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE; - - ret = m5mols_write(&info->sd, AWB_LOCK, awb_lock ? - REG_AWB_LOCK : REG_AWB_UNLOCK); - if (ret) - return ret; - } - - if (!info->ver.af || !af_lock) - return ret; - - if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS) - ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); - - return ret; -} - -static int m5mols_set_metering_mode(struct m5mols_info *info, int mode) -{ - unsigned int metering; - - switch (mode) { - case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: - metering = REG_AE_CENTER; - break; - case V4L2_EXPOSURE_METERING_SPOT: - metering = REG_AE_SPOT; - break; - default: - metering = REG_AE_ALL; - break; - } - - return m5mols_write(&info->sd, AE_MODE, metering); -} - -static int m5mols_set_exposure(struct m5mols_info *info, int exposure) -{ - struct v4l2_subdev *sd = &info->sd; - int ret = 0; - - if (exposure == V4L2_EXPOSURE_AUTO) { - /* Unlock auto exposure */ - info->lock_3a->val &= ~V4L2_LOCK_EXPOSURE; - m5mols_3a_lock(info, info->lock_3a); - - ret = m5mols_set_metering_mode(info, info->metering->val); - if (ret < 0) - return ret; - - v4l2_dbg(1, m5mols_debug, sd, - "%s: exposure bias: %#x, metering: %#x\n", - __func__, info->exposure_bias->val, - info->metering->val); - - return m5mols_write(sd, AE_INDEX, info->exposure_bias->val); - } - - if (exposure == V4L2_EXPOSURE_MANUAL) { - ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); - if (ret == 0) - ret = m5mols_write(sd, AE_MAN_GAIN_MON, - info->exposure->val); - if (ret == 0) - ret = m5mols_write(sd, AE_MAN_GAIN_CAP, - info->exposure->val); - - v4l2_dbg(1, m5mols_debug, sd, "%s: exposure: %#x\n", - __func__, info->exposure->val); - } - - return ret; -} - -static int m5mols_set_white_balance(struct m5mols_info *info, int val) -{ - static const unsigned short wb[][2] = { - { V4L2_WHITE_BALANCE_INCANDESCENT, REG_AWB_INCANDESCENT }, - { V4L2_WHITE_BALANCE_FLUORESCENT, REG_AWB_FLUORESCENT_1 }, - { V4L2_WHITE_BALANCE_FLUORESCENT_H, REG_AWB_FLUORESCENT_2 }, - { V4L2_WHITE_BALANCE_HORIZON, REG_AWB_HORIZON }, - { V4L2_WHITE_BALANCE_DAYLIGHT, REG_AWB_DAYLIGHT }, - { V4L2_WHITE_BALANCE_FLASH, REG_AWB_LEDLIGHT }, - { V4L2_WHITE_BALANCE_CLOUDY, REG_AWB_CLOUDY }, - { V4L2_WHITE_BALANCE_SHADE, REG_AWB_SHADE }, - { V4L2_WHITE_BALANCE_AUTO, REG_AWB_AUTO }, - }; - int i; - struct v4l2_subdev *sd = &info->sd; - int ret = -EINVAL; - - for (i = 0; i < ARRAY_SIZE(wb); i++) { - int awb; - if (wb[i][0] != val) - continue; - - v4l2_dbg(1, m5mols_debug, sd, - "Setting white balance to: %#x\n", wb[i][0]); - - awb = wb[i][0] == V4L2_WHITE_BALANCE_AUTO; - ret = m5mols_write(sd, AWB_MODE, awb ? REG_AWB_AUTO : - REG_AWB_PRESET); - if (ret < 0) - return ret; - - if (!awb) - ret = m5mols_write(sd, AWB_MANUAL, wb[i][1]); - } - - return ret; -} - -static int m5mols_set_saturation(struct m5mols_info *info, int val) -{ - int ret = m5mols_write(&info->sd, MON_CHROMA_LVL, val); - if (ret < 0) - return ret; - - return m5mols_write(&info->sd, MON_CHROMA_EN, REG_CHROMA_ON); -} - -static int m5mols_set_color_effect(struct m5mols_info *info, int val) -{ - unsigned int m_effect = REG_COLOR_EFFECT_OFF; - unsigned int p_effect = REG_EFFECT_OFF; - unsigned int cfix_r = 0, cfix_b = 0; - struct v4l2_subdev *sd = &info->sd; - int ret = 0; - - switch (val) { - case V4L2_COLORFX_BW: - m_effect = REG_COLOR_EFFECT_ON; - break; - case V4L2_COLORFX_NEGATIVE: - p_effect = REG_EFFECT_NEGA; - break; - case V4L2_COLORFX_EMBOSS: - p_effect = REG_EFFECT_EMBOSS; - break; - case V4L2_COLORFX_SEPIA: - m_effect = REG_COLOR_EFFECT_ON; - cfix_r = REG_CFIXR_SEPIA; - cfix_b = REG_CFIXB_SEPIA; - break; - } - - ret = m5mols_write(sd, PARM_EFFECT, p_effect); - if (!ret) - ret = m5mols_write(sd, MON_EFFECT, m_effect); - - if (ret == 0 && m_effect == REG_COLOR_EFFECT_ON) { - ret = m5mols_write(sd, MON_CFIXR, cfix_r); - if (!ret) - ret = m5mols_write(sd, MON_CFIXB, cfix_b); - } - - v4l2_dbg(1, m5mols_debug, sd, - "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n", - p_effect, m_effect, cfix_r, cfix_b, ret); - - return ret; -} - -static int m5mols_set_iso(struct m5mols_info *info, int auto_iso) -{ - u32 iso = auto_iso ? 0 : info->iso->val + 1; - - return m5mols_write(&info->sd, AE_ISO, iso); -} - -static int m5mols_set_wdr(struct m5mols_info *info, int wdr) -{ - int ret; - - ret = m5mols_write(&info->sd, MON_TONE_CTL, wdr ? 9 : 5); - if (ret < 0) - return ret; - - ret = m5mols_set_mode(info, REG_CAPTURE); - if (ret < 0) - return ret; - - return m5mols_write(&info->sd, CAPP_WDR_EN, wdr); -} - -static int m5mols_set_stabilization(struct m5mols_info *info, int val) -{ - struct v4l2_subdev *sd = &info->sd; - unsigned int evp = val ? 0xe : 0x0; - int ret; - - ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, evp); - if (ret < 0) - return ret; - - return m5mols_write(sd, AE_EV_PRESET_CAPTURE, evp); -} - -static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = to_sd(ctrl); - struct m5mols_info *info = to_m5mols(sd); - int ret = 0; - u8 status = REG_ISO_AUTO; - - v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n", - __func__, ctrl->name, info->isp_ready); - - if (!info->isp_ready) - return -EBUSY; - - switch (ctrl->id) { - case V4L2_CID_ISO_SENSITIVITY_AUTO: - ret = m5mols_read_u8(sd, AE_ISO, &sta |