Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] Add support for M-5MOLS 8 Mega Pixel camera ISP

Add I2C/V4L2 subdev driver for M-5MOLS integrated image signal processor
with 8 Mega Pixel sensor.

Signed-off-by: HeungJun, Kim <riverful.kim@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

HeungJun, Kim and committed by
Mauro Carvalho Chehab
bc125106 cf252206

+2235
+2
drivers/media/video/Kconfig
··· 757 757 ---help--- 758 758 This driver supports NOON010PC30 CIF camera from Siliconfile 759 759 760 + source "drivers/media/video/m5mols/Kconfig" 761 + 760 762 config VIDEO_OMAP3 761 763 tristate "OMAP 3 Camera support (EXPERIMENTAL)" 762 764 select OMAP_IOMMU
+1
drivers/media/video/Makefile
··· 69 69 obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o 70 70 obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o 71 71 obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o 72 + obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ 72 73 73 74 obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o 74 75 obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
+5
drivers/media/video/m5mols/Kconfig
··· 1 + config VIDEO_M5MOLS 2 + tristate "Fujitsu M-5MOLS 8MP sensor support" 3 + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 4 + ---help--- 5 + This driver supports Fujitsu M-5MOLS camera sensor with ISP
+3
drivers/media/video/m5mols/Makefile
··· 1 + m5mols-objs := m5mols_core.o m5mols_controls.o m5mols_capture.o 2 + 3 + obj-$(CONFIG_VIDEO_M5MOLS) += m5mols.o
+296
drivers/media/video/m5mols/m5mols.h
··· 1 + /* 2 + * Header for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #ifndef M5MOLS_H 17 + #define M5MOLS_H 18 + 19 + #include <media/v4l2-subdev.h> 20 + #include "m5mols_reg.h" 21 + 22 + extern int m5mols_debug; 23 + 24 + #define to_m5mols(__sd) container_of(__sd, struct m5mols_info, sd) 25 + 26 + #define to_sd(__ctrl) \ 27 + (&container_of(__ctrl->handler, struct m5mols_info, handle)->sd) 28 + 29 + enum m5mols_restype { 30 + M5MOLS_RESTYPE_MONITOR, 31 + M5MOLS_RESTYPE_CAPTURE, 32 + M5MOLS_RESTYPE_MAX, 33 + }; 34 + 35 + /** 36 + * struct m5mols_resolution - structure for the resolution 37 + * @type: resolution type according to the pixel code 38 + * @width: width of the resolution 39 + * @height: height of the resolution 40 + * @reg: resolution preset register value 41 + */ 42 + struct m5mols_resolution { 43 + u8 reg; 44 + enum m5mols_restype type; 45 + u16 width; 46 + u16 height; 47 + }; 48 + 49 + /** 50 + * struct m5mols_exif - structure for the EXIF information of M-5MOLS 51 + * @exposure_time: exposure time register value 52 + * @shutter_speed: speed of the shutter register value 53 + * @aperture: aperture register value 54 + * @exposure_bias: it calls also EV bias 55 + * @iso_speed: ISO register value 56 + * @flash: status register value of the flash 57 + * @sdr: status register value of the Subject Distance Range 58 + * @qval: not written exact meaning in document 59 + */ 60 + struct m5mols_exif { 61 + u32 exposure_time; 62 + u32 shutter_speed; 63 + u32 aperture; 64 + u32 brightness; 65 + u32 exposure_bias; 66 + u16 iso_speed; 67 + u16 flash; 68 + u16 sdr; 69 + u16 qval; 70 + }; 71 + 72 + /** 73 + * struct m5mols_capture - Structure for the capture capability 74 + * @exif: EXIF information 75 + * @main: size in bytes of the main image 76 + * @thumb: size in bytes of the thumb image, if it was accompanied 77 + * @total: total size in bytes of the produced image 78 + */ 79 + struct m5mols_capture { 80 + struct m5mols_exif exif; 81 + u32 main; 82 + u32 thumb; 83 + u32 total; 84 + }; 85 + 86 + /** 87 + * struct m5mols_scenemode - structure for the scenemode capability 88 + * @metering: metering light register value 89 + * @ev_bias: EV bias register value 90 + * @wb_mode: mode which means the WhiteBalance is Auto or Manual 91 + * @wb_preset: whitebalance preset register value in the Manual mode 92 + * @chroma_en: register value whether the Chroma capability is enabled or not 93 + * @chroma_lvl: chroma's level register value 94 + * @edge_en: register value Whether the Edge capability is enabled or not 95 + * @edge_lvl: edge's level register value 96 + * @af_range: Auto Focus's range 97 + * @fd_mode: Face Detection mode 98 + * @mcc: Multi-axis Color Conversion which means emotion color 99 + * @light: status of the Light 100 + * @flash: status of the Flash 101 + * @tone: Tone color which means Contrast 102 + * @iso: ISO register value 103 + * @capt_mode: Mode of the Image Stabilization while the camera capturing 104 + * @wdr: Wide Dynamic Range register value 105 + * 106 + * The each value according to each scenemode is recommended in the documents. 107 + */ 108 + struct m5mols_scenemode { 109 + u32 metering; 110 + u32 ev_bias; 111 + u32 wb_mode; 112 + u32 wb_preset; 113 + u32 chroma_en; 114 + u32 chroma_lvl; 115 + u32 edge_en; 116 + u32 edge_lvl; 117 + u32 af_range; 118 + u32 fd_mode; 119 + u32 mcc; 120 + u32 light; 121 + u32 flash; 122 + u32 tone; 123 + u32 iso; 124 + u32 capt_mode; 125 + u32 wdr; 126 + }; 127 + 128 + /** 129 + * struct m5mols_version - firmware version information 130 + * @customer: customer information 131 + * @project: version of project information according to customer 132 + * @fw: firmware revision 133 + * @hw: hardware revision 134 + * @param: version of the parameter 135 + * @awb: Auto WhiteBalance algorithm version 136 + * @str: information about manufacturer and packaging vendor 137 + * @af: Auto Focus version 138 + * 139 + * The register offset starts the customer version at 0x0, and it ends 140 + * the awb version at 0x09. The customer, project information occupies 1 bytes 141 + * each. And also the fw, hw, param, awb each requires 2 bytes. The str is 142 + * unique string associated with firmware's version. It includes information 143 + * about manufacturer and the vendor of the sensor's packaging. The least 144 + * significant 2 bytes of the string indicate packaging manufacturer. 145 + */ 146 + #define VERSION_STRING_SIZE 22 147 + struct m5mols_version { 148 + u8 customer; 149 + u8 project; 150 + u16 fw; 151 + u16 hw; 152 + u16 param; 153 + u16 awb; 154 + u8 str[VERSION_STRING_SIZE]; 155 + u8 af; 156 + }; 157 + #define VERSION_SIZE sizeof(struct m5mols_version) 158 + 159 + /** 160 + * struct m5mols_info - M-5MOLS driver data structure 161 + * @pdata: platform data 162 + * @sd: v4l-subdev instance 163 + * @pad: media pad 164 + * @ffmt: current fmt according to resolution type 165 + * @res_type: current resolution type 166 + * @code: current code 167 + * @irq_waitq: waitqueue for the capture 168 + * @work_irq: workqueue for the IRQ 169 + * @flags: state variable for the interrupt handler 170 + * @handle: control handler 171 + * @autoexposure: Auto Exposure control 172 + * @exposure: Exposure control 173 + * @autowb: Auto White Balance control 174 + * @colorfx: Color effect control 175 + * @saturation: Saturation control 176 + * @zoom: Zoom control 177 + * @ver: information of the version 178 + * @cap: the capture mode attributes 179 + * @power: current sensor's power status 180 + * @ctrl_sync: true means all controls of the sensor are initialized 181 + * @int_capture: true means the capture interrupt is issued once 182 + * @lock_ae: true means the Auto Exposure is locked 183 + * @lock_awb: true means the Aut WhiteBalance is locked 184 + * @resolution: register value for current resolution 185 + * @interrupt: register value for current interrupt status 186 + * @mode: register value for current operation mode 187 + * @mode_save: register value for current operation mode for saving 188 + * @set_power: optional power callback to the board code 189 + */ 190 + struct m5mols_info { 191 + const struct m5mols_platform_data *pdata; 192 + struct v4l2_subdev sd; 193 + struct media_pad pad; 194 + struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; 195 + int res_type; 196 + enum v4l2_mbus_pixelcode code; 197 + wait_queue_head_t irq_waitq; 198 + struct work_struct work_irq; 199 + unsigned long flags; 200 + 201 + struct v4l2_ctrl_handler handle; 202 + /* Autoexposure/exposure control cluster */ 203 + struct { 204 + struct v4l2_ctrl *autoexposure; 205 + struct v4l2_ctrl *exposure; 206 + }; 207 + struct v4l2_ctrl *autowb; 208 + struct v4l2_ctrl *colorfx; 209 + struct v4l2_ctrl *saturation; 210 + struct v4l2_ctrl *zoom; 211 + 212 + struct m5mols_version ver; 213 + struct m5mols_capture cap; 214 + bool power; 215 + bool ctrl_sync; 216 + bool lock_ae; 217 + bool lock_awb; 218 + u8 resolution; 219 + u32 interrupt; 220 + u32 mode; 221 + u32 mode_save; 222 + int (*set_power)(struct device *dev, int on); 223 + }; 224 + 225 + #define ST_CAPT_IRQ 0 226 + 227 + #define is_powered(__info) (__info->power) 228 + #define is_ctrl_synced(__info) (__info->ctrl_sync) 229 + #define is_available_af(__info) (__info->ver.af) 230 + #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) 231 + #define is_manufacturer(__info, __manufacturer) \ 232 + (__info->ver.str[0] == __manufacturer[0] && \ 233 + __info->ver.str[1] == __manufacturer[1]) 234 + /* 235 + * I2C operation of the M-5MOLS 236 + * 237 + * The I2C read operation of the M-5MOLS requires 2 messages. The first 238 + * message sends the information about the command, command category, and total 239 + * message size. The second message is used to retrieve the data specifed in 240 + * the first message 241 + * 242 + * 1st message 2nd message 243 + * +-------+---+----------+-----+-------+ +------+------+------+------+ 244 + * | size1 | R | category | cmd | size2 | | d[0] | d[1] | d[2] | d[3] | 245 + * +-------+---+----------+-----+-------+ +------+------+------+------+ 246 + * - size1: message data size(5 in this case) 247 + * - size2: desired buffer size of the 2nd message 248 + * - d[0..3]: according to size2 249 + * 250 + * The I2C write operation needs just one message. The message includes 251 + * category, command, total size, and desired data. 252 + * 253 + * 1st message 254 + * +-------+---+----------+-----+------+------+------+------+ 255 + * | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] | 256 + * +-------+---+----------+-----+------+------+------+------+ 257 + * - d[0..3]: according to size1 258 + */ 259 + int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); 260 + int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); 261 + int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value); 262 + 263 + /* 264 + * Mode operation of the M-5MOLS 265 + * 266 + * Changing the mode of the M-5MOLS is needed right executing order. 267 + * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed 268 + * by user. There are various categories associated with each mode. 269 + * 270 + * +============================================================+ 271 + * | mode | category | 272 + * +============================================================+ 273 + * | FLASH | FLASH(only after Stand-by or Power-on) | 274 + * | SYSTEM | SYSTEM(only after sensor arm-booting) | 275 + * | PARAMETER | PARAMETER | 276 + * | MONITOR | MONITOR(preview), Auto Focus, Face Detection | 277 + * | CAPTURE | Single CAPTURE, Preview(recording) | 278 + * +============================================================+ 279 + * 280 + * The available executing order between each modes are as follows: 281 + * PARAMETER <---> MONITOR <---> CAPTURE 282 + */ 283 + int m5mols_mode(struct m5mols_info *info, u32 mode); 284 + 285 + int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg); 286 + int m5mols_sync_controls(struct m5mols_info *info); 287 + int m5mols_start_capture(struct m5mols_info *info); 288 + int m5mols_do_scenemode(struct m5mols_info *info, u32 mode); 289 + int m5mols_lock_3a(struct m5mols_info *info, bool lock); 290 + int m5mols_set_ctrl(struct v4l2_ctrl *ctrl); 291 + 292 + /* The firmware function */ 293 + int m5mols_update_fw(struct v4l2_subdev *sd, 294 + int (*set_power)(struct m5mols_info *, bool)); 295 + 296 + #endif /* M5MOLS_H */
+191
drivers/media/video/m5mols/m5mols_capture.c
··· 1 + /* 2 + * The Capture code for Fujitsu M-5MOLS ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #include <linux/i2c.h> 17 + #include <linux/slab.h> 18 + #include <linux/irq.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/delay.h> 21 + #include <linux/version.h> 22 + #include <linux/gpio.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/videodev2.h> 25 + #include <linux/version.h> 26 + #include <media/v4l2-ctrls.h> 27 + #include <media/v4l2-device.h> 28 + #include <media/v4l2-subdev.h> 29 + #include <media/m5mols.h> 30 + 31 + #include "m5mols.h" 32 + #include "m5mols_reg.h" 33 + 34 + static int m5mols_capture_error_handler(struct m5mols_info *info, 35 + int timeout) 36 + { 37 + int ret; 38 + 39 + /* Disable all interrupts and clear relevant interrupt staus bits */ 40 + ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE, 41 + info->interrupt & ~(REG_INT_CAPTURE)); 42 + if (ret) 43 + return ret; 44 + 45 + if (timeout == 0) 46 + return -ETIMEDOUT; 47 + 48 + return 0; 49 + } 50 + /** 51 + * m5mols_read_rational - I2C read of a rational number 52 + * 53 + * Read numerator and denominator from registers @addr_num and @addr_den 54 + * respectively and return the division result in @val. 55 + */ 56 + static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num, 57 + u32 addr_den, u32 *val) 58 + { 59 + u32 num, den; 60 + 61 + int ret = m5mols_read(sd, addr_num, &num); 62 + if (!ret) 63 + ret = m5mols_read(sd, addr_den, &den); 64 + if (ret) 65 + return ret; 66 + *val = den == 0 ? 0 : num / den; 67 + return ret; 68 + } 69 + 70 + /** 71 + * m5mols_capture_info - Gather captured image information 72 + * 73 + * For now it gathers only EXIF information and file size. 74 + */ 75 + static int m5mols_capture_info(struct m5mols_info *info) 76 + { 77 + struct m5mols_exif *exif = &info->cap.exif; 78 + struct v4l2_subdev *sd = &info->sd; 79 + int ret; 80 + 81 + ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU, 82 + EXIF_INFO_EXPTIME_DE, &exif->exposure_time); 83 + if (ret) 84 + return ret; 85 + ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE, 86 + &exif->shutter_speed); 87 + if (ret) 88 + return ret; 89 + ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE, 90 + &exif->aperture); 91 + if (ret) 92 + return ret; 93 + ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE, 94 + &exif->brightness); 95 + if (ret) 96 + return ret; 97 + ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE, 98 + &exif->exposure_bias); 99 + if (ret) 100 + return ret; 101 + 102 + ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed); 103 + if (!ret) 104 + ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash); 105 + if (!ret) 106 + ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr); 107 + if (!ret) 108 + ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval); 109 + if (ret) 110 + return ret; 111 + 112 + if (!ret) 113 + ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main); 114 + if (!ret) 115 + ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb); 116 + if (!ret) 117 + info->cap.total = info->cap.main + info->cap.thumb; 118 + 119 + return ret; 120 + } 121 + 122 + int m5mols_start_capture(struct m5mols_info *info) 123 + { 124 + struct v4l2_subdev *sd = &info->sd; 125 + u32 resolution = info->resolution; 126 + int timeout; 127 + int ret; 128 + 129 + /* 130 + * Preparing capture. Setting control & interrupt before entering 131 + * capture mode 132 + * 133 + * 1) change to MONITOR mode for operating control & interrupt 134 + * 2) set controls (considering v4l2_control value & lock 3A) 135 + * 3) set interrupt 136 + * 4) change to CAPTURE mode 137 + */ 138 + ret = m5mols_mode(info, REG_MONITOR); 139 + if (!ret) 140 + ret = m5mols_sync_controls(info); 141 + if (!ret) 142 + ret = m5mols_lock_3a(info, true); 143 + if (!ret) 144 + ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); 145 + if (!ret) 146 + ret = m5mols_mode(info, REG_CAPTURE); 147 + if (!ret) { 148 + /* Wait for capture interrupt, after changing capture mode */ 149 + timeout = wait_event_interruptible_timeout(info->irq_waitq, 150 + test_bit(ST_CAPT_IRQ, &info->flags), 151 + msecs_to_jiffies(2000)); 152 + if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) 153 + ret = m5mols_capture_error_handler(info, timeout); 154 + } 155 + if (!ret) 156 + ret = m5mols_lock_3a(info, false); 157 + if (ret) 158 + return ret; 159 + /* 160 + * Starting capture. Setting capture frame count and resolution and 161 + * the format(available format: JPEG, Bayer RAW, YUV). 162 + * 163 + * 1) select single or multi(enable to 25), format, size 164 + * 2) set interrupt 165 + * 3) start capture(for main image, now) 166 + * 4) get information 167 + * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device) 168 + */ 169 + ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); 170 + if (!ret) 171 + ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); 172 + if (!ret) 173 + ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); 174 + if (!ret) 175 + ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); 176 + if (!ret) 177 + ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); 178 + if (!ret) { 179 + /* Wait for the capture completion interrupt */ 180 + timeout = wait_event_interruptible_timeout(info->irq_waitq, 181 + test_bit(ST_CAPT_IRQ, &info->flags), 182 + msecs_to_jiffies(2000)); 183 + if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) { 184 + ret = m5mols_capture_info(info); 185 + if (!ret) 186 + v4l2_subdev_notify(sd, 0, &info->cap.total); 187 + } 188 + } 189 + 190 + return m5mols_capture_error_handler(info, timeout); 191 + }
+299
drivers/media/video/m5mols/m5mols_controls.c
··· 1 + /* 2 + * Controls for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #include <linux/i2c.h> 17 + #include <linux/delay.h> 18 + #include <linux/videodev2.h> 19 + #include <media/v4l2-ctrls.h> 20 + 21 + #include "m5mols.h" 22 + #include "m5mols_reg.h" 23 + 24 + static struct m5mols_scenemode m5mols_default_scenemode[] = { 25 + [REG_SCENE_NORMAL] = { 26 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 27 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 28 + REG_AF_NORMAL, REG_FD_OFF, 29 + REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF, 30 + 5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 31 + }, 32 + [REG_SCENE_PORTRAIT] = { 33 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 34 + REG_CHROMA_ON, 3, REG_EDGE_ON, 4, 35 + REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME, 36 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 37 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 38 + }, 39 + [REG_SCENE_LANDSCAPE] = { 40 + REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 41 + REG_CHROMA_ON, 4, REG_EDGE_ON, 6, 42 + REG_AF_NORMAL, REG_FD_OFF, 43 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 44 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 45 + }, 46 + [REG_SCENE_SPORTS] = { 47 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 48 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 49 + REG_AF_NORMAL, REG_FD_OFF, 50 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 51 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 52 + }, 53 + [REG_SCENE_PARTY_INDOOR] = { 54 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 55 + REG_CHROMA_ON, 4, REG_EDGE_ON, 5, 56 + REG_AF_NORMAL, REG_FD_OFF, 57 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 58 + 6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF, 59 + }, 60 + [REG_SCENE_BEACH_SNOW] = { 61 + REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0, 62 + REG_CHROMA_ON, 4, REG_EDGE_ON, 5, 63 + REG_AF_NORMAL, REG_FD_OFF, 64 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 65 + 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, 66 + }, 67 + [REG_SCENE_SUNSET] = { 68 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, 69 + REG_AWB_DAYLIGHT, 70 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 71 + REG_AF_NORMAL, REG_FD_OFF, 72 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 73 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 74 + }, 75 + [REG_SCENE_DAWN_DUSK] = { 76 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET, 77 + REG_AWB_FLUORESCENT_1, 78 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 79 + REG_AF_NORMAL, REG_FD_OFF, 80 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 81 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 82 + }, 83 + [REG_SCENE_FALL] = { 84 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 85 + REG_CHROMA_ON, 5, REG_EDGE_ON, 5, 86 + REG_AF_NORMAL, REG_FD_OFF, 87 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 88 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 89 + }, 90 + [REG_SCENE_NIGHT] = { 91 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 92 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 93 + REG_AF_NORMAL, REG_FD_OFF, 94 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 95 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 96 + }, 97 + [REG_SCENE_AGAINST_LIGHT] = { 98 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 99 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 100 + REG_AF_NORMAL, REG_FD_OFF, 101 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 102 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 103 + }, 104 + [REG_SCENE_FIRE] = { 105 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 106 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 107 + REG_AF_NORMAL, REG_FD_OFF, 108 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 109 + 6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF, 110 + }, 111 + [REG_SCENE_TEXT] = { 112 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 113 + REG_CHROMA_ON, 3, REG_EDGE_ON, 7, 114 + REG_AF_MACRO, REG_FD_OFF, 115 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 116 + 6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON, 117 + }, 118 + [REG_SCENE_CANDLE] = { 119 + REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0, 120 + REG_CHROMA_ON, 3, REG_EDGE_ON, 5, 121 + REG_AF_NORMAL, REG_FD_OFF, 122 + REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF, 123 + 6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF, 124 + }, 125 + }; 126 + 127 + /** 128 + * m5mols_do_scenemode() - Change current scenemode 129 + * @mode: Desired mode of the scenemode 130 + * 131 + * WARNING: The execution order is important. Do not change the order. 132 + */ 133 + int m5mols_do_scenemode(struct m5mols_info *info, u32 mode) 134 + { 135 + struct v4l2_subdev *sd = &info->sd; 136 + struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; 137 + int ret; 138 + 139 + if (mode > REG_SCENE_CANDLE) 140 + return -EINVAL; 141 + 142 + ret = m5mols_lock_3a(info, false); 143 + if (!ret) 144 + ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); 145 + if (!ret) 146 + ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode); 147 + if (!ret) 148 + ret = m5mols_write(sd, AE_MODE, scenemode.metering); 149 + if (!ret) 150 + ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias); 151 + if (!ret) 152 + ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode); 153 + if (!ret) 154 + ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset); 155 + if (!ret) 156 + ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en); 157 + if (!ret) 158 + ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl); 159 + if (!ret) 160 + ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en); 161 + if (!ret) 162 + ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl); 163 + if (!ret && is_available_af(info)) 164 + ret = m5mols_write(sd, AF_MODE, scenemode.af_range); 165 + if (!ret && is_available_af(info)) 166 + ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode); 167 + if (!ret) 168 + ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone); 169 + if (!ret) 170 + ret = m5mols_write(sd, AE_ISO, scenemode.iso); 171 + if (!ret) 172 + ret = m5mols_mode(info, REG_CAPTURE); 173 + if (!ret) 174 + ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); 175 + if (!ret) 176 + ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc); 177 + if (!ret) 178 + ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light); 179 + if (!ret) 180 + ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash); 181 + if (!ret) 182 + ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); 183 + if (!ret) 184 + ret = m5mols_mode(info, REG_MONITOR); 185 + 186 + return ret; 187 + } 188 + 189 + static int m5mols_lock_ae(struct m5mols_info *info, bool lock) 190 + { 191 + int ret = 0; 192 + 193 + if (info->lock_ae != lock) 194 + ret = m5mols_write(&info->sd, AE_LOCK, 195 + lock ? REG_AE_LOCK : REG_AE_UNLOCK); 196 + if (!ret) 197 + info->lock_ae = lock; 198 + 199 + return ret; 200 + } 201 + 202 + static int m5mols_lock_awb(struct m5mols_info *info, bool lock) 203 + { 204 + int ret = 0; 205 + 206 + if (info->lock_awb != lock) 207 + ret = m5mols_write(&info->sd, AWB_LOCK, 208 + lock ? REG_AWB_LOCK : REG_AWB_UNLOCK); 209 + if (!ret) 210 + info->lock_awb = lock; 211 + 212 + return ret; 213 + } 214 + 215 + /* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */ 216 + int m5mols_lock_3a(struct m5mols_info *info, bool lock) 217 + { 218 + int ret; 219 + 220 + ret = m5mols_lock_ae(info, lock); 221 + if (!ret) 222 + ret = m5mols_lock_awb(info, lock); 223 + /* Don't need to handle unlocking AF */ 224 + if (!ret && is_available_af(info) && lock) 225 + ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); 226 + 227 + return ret; 228 + } 229 + 230 + /* m5mols_set_ctrl() - The main s_ctrl function called by m5mols_set_ctrl() */ 231 + int m5mols_set_ctrl(struct v4l2_ctrl *ctrl) 232 + { 233 + struct v4l2_subdev *sd = to_sd(ctrl); 234 + struct m5mols_info *info = to_m5mols(sd); 235 + int ret; 236 + 237 + switch (ctrl->id) { 238 + case V4L2_CID_ZOOM_ABSOLUTE: 239 + return m5mols_write(sd, MON_ZOOM, ctrl->val); 240 + 241 + case V4L2_CID_EXPOSURE_AUTO: 242 + ret = m5mols_lock_ae(info, 243 + ctrl->val == V4L2_EXPOSURE_AUTO ? false : true); 244 + if (!ret && ctrl->val == V4L2_EXPOSURE_AUTO) 245 + ret = m5mols_write(sd, AE_MODE, REG_AE_ALL); 246 + if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL) { 247 + int val = info->exposure->val; 248 + ret = m5mols_write(sd, AE_MODE, REG_AE_OFF); 249 + if (!ret) 250 + ret = m5mols_write(sd, AE_MAN_GAIN_MON, val); 251 + if (!ret) 252 + ret = m5mols_write(sd, AE_MAN_GAIN_CAP, val); 253 + } 254 + return ret; 255 + 256 + case V4L2_CID_AUTO_WHITE_BALANCE: 257 + ret = m5mols_lock_awb(info, ctrl->val ? false : true); 258 + if (!ret) 259 + ret = m5mols_write(sd, AWB_MODE, ctrl->val ? 260 + REG_AWB_AUTO : REG_AWB_PRESET); 261 + return ret; 262 + 263 + case V4L2_CID_SATURATION: 264 + ret = m5mols_write(sd, MON_CHROMA_LVL, ctrl->val); 265 + if (!ret) 266 + ret = m5mols_write(sd, MON_CHROMA_EN, REG_CHROMA_ON); 267 + return ret; 268 + 269 + case V4L2_CID_COLORFX: 270 + /* 271 + * This control uses two kinds of registers: normal & color. 272 + * The normal effect belongs to category 1, while the color 273 + * one belongs to category 2. 274 + * 275 + * The normal effect uses one register: CAT1_EFFECT. 276 + * The color effect uses three registers: 277 + * CAT2_COLOR_EFFECT, CAT2_CFIXR, CAT2_CFIXB. 278 + */ 279 + ret = m5mols_write(sd, PARM_EFFECT, 280 + ctrl->val == V4L2_COLORFX_NEGATIVE ? REG_EFFECT_NEGA : 281 + ctrl->val == V4L2_COLORFX_EMBOSS ? REG_EFFECT_EMBOSS : 282 + REG_EFFECT_OFF); 283 + if (!ret) 284 + ret = m5mols_write(sd, MON_EFFECT, 285 + ctrl->val == V4L2_COLORFX_SEPIA ? 286 + REG_COLOR_EFFECT_ON : REG_COLOR_EFFECT_OFF); 287 + if (!ret) 288 + ret = m5mols_write(sd, MON_CFIXR, 289 + ctrl->val == V4L2_COLORFX_SEPIA ? 290 + REG_CFIXR_SEPIA : 0); 291 + if (!ret) 292 + ret = m5mols_write(sd, MON_CFIXB, 293 + ctrl->val == V4L2_COLORFX_SEPIA ? 294 + REG_CFIXB_SEPIA : 0); 295 + return ret; 296 + } 297 + 298 + return -EINVAL; 299 + }
+1004
drivers/media/video/m5mols/m5mols_core.c
··· 1 + /* 2 + * Driver for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #include <linux/i2c.h> 17 + #include <linux/slab.h> 18 + #include <linux/irq.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/delay.h> 21 + #include <linux/version.h> 22 + #include <linux/gpio.h> 23 + #include <linux/regulator/consumer.h> 24 + #include <linux/videodev2.h> 25 + #include <media/v4l2-ctrls.h> 26 + #include <media/v4l2-device.h> 27 + #include <media/v4l2-subdev.h> 28 + #include <media/m5mols.h> 29 + 30 + #include "m5mols.h" 31 + #include "m5mols_reg.h" 32 + 33 + int m5mols_debug; 34 + module_param(m5mols_debug, int, 0644); 35 + 36 + #define MODULE_NAME "M5MOLS" 37 + #define M5MOLS_I2C_CHECK_RETRY 500 38 + 39 + /* The regulator consumer names for external voltage regulators */ 40 + static struct regulator_bulk_data supplies[] = { 41 + { 42 + .supply = "core", /* ARM core power, 1.2V */ 43 + }, { 44 + .supply = "dig_18", /* digital power 1, 1.8V */ 45 + }, { 46 + .supply = "d_sensor", /* sensor power 1, 1.8V */ 47 + }, { 48 + .supply = "dig_28", /* digital power 2, 2.8V */ 49 + }, { 50 + .supply = "a_sensor", /* analog power */ 51 + }, { 52 + .supply = "dig_12", /* digital power 3, 1.2V */ 53 + }, 54 + }; 55 + 56 + static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = { 57 + [M5MOLS_RESTYPE_MONITOR] = { 58 + .width = 1920, 59 + .height = 1080, 60 + .code = V4L2_MBUS_FMT_VYUY8_2X8, 61 + .field = V4L2_FIELD_NONE, 62 + .colorspace = V4L2_COLORSPACE_JPEG, 63 + }, 64 + [M5MOLS_RESTYPE_CAPTURE] = { 65 + .width = 1920, 66 + .height = 1080, 67 + .code = V4L2_MBUS_FMT_JPEG_1X8, 68 + .field = V4L2_FIELD_NONE, 69 + .colorspace = V4L2_COLORSPACE_JPEG, 70 + }, 71 + }; 72 + #define SIZE_DEFAULT_FFMT ARRAY_SIZE(m5mols_default_ffmt) 73 + 74 + static const struct m5mols_resolution m5mols_reg_res[] = { 75 + { 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 }, /* SUB-QCIF */ 76 + { 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 }, /* QQVGA */ 77 + { 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 }, /* QCIF */ 78 + { 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 }, 79 + { 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 }, /* QVGA */ 80 + { 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 }, /* QVGA */ 81 + { 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 }, /* WQVGA */ 82 + { 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 }, /* WQVGA */ 83 + { 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 }, /* CIF */ 84 + { 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 }, 85 + { 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 }, /* qHD */ 86 + { 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 }, /* VGA */ 87 + { 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 }, 88 + { 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 }, /* WVGA */ 89 + { 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 }, /* SVGA */ 90 + { 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 }, /* HD */ 91 + { 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 }, /* 1080p */ 92 + { 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 }, /* 2.63fps 8M */ 93 + { 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 }, /* AHS_MON debug */ 94 + 95 + { 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 }, /* QVGA */ 96 + { 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 }, /* WQVGA */ 97 + { 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 }, 98 + { 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 }, /* qHD */ 99 + { 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 }, /* VGA */ 100 + { 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 }, /* WVGA */ 101 + { 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 }, /* HD */ 102 + { 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 }, /* 1M */ 103 + { 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 }, /* 2M */ 104 + { 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 }, /* Full-HD */ 105 + { 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 }, /* 3Mega */ 106 + { 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 }, 107 + { 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 }, /* 4Mega */ 108 + { 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 }, 109 + { 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 }, /* 5Mega */ 110 + { 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 }, /* 6Mega */ 111 + { 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 }, 112 + { 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 }, /* 8Mega */ 113 + }; 114 + 115 + /** 116 + * m5mols_swap_byte - an byte array to integer conversion function 117 + * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet 118 + * 119 + * Convert I2C data byte array with performing any required byte 120 + * reordering to assure proper values for each data type, regardless 121 + * of the architecture endianness. 122 + */ 123 + static u32 m5mols_swap_byte(u8 *data, u8 length) 124 + { 125 + if (length == 1) 126 + return *data; 127 + else if (length == 2) 128 + return be16_to_cpu(*((u16 *)data)); 129 + else 130 + return be32_to_cpu(*((u32 *)data)); 131 + } 132 + 133 + /** 134 + * m5mols_read - I2C read function 135 + * @reg: combination of size, category and command for the I2C packet 136 + * @val: read value 137 + */ 138 + int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val) 139 + { 140 + struct i2c_client *client = v4l2_get_subdevdata(sd); 141 + u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; 142 + u8 size = I2C_SIZE(reg); 143 + u8 category = I2C_CATEGORY(reg); 144 + u8 cmd = I2C_COMMAND(reg); 145 + struct i2c_msg msg[2]; 146 + u8 wbuf[5]; 147 + int ret; 148 + 149 + if (!client->adapter) 150 + return -ENODEV; 151 + 152 + if (size != 1 && size != 2 && size != 4) { 153 + v4l2_err(sd, "Wrong data size\n"); 154 + return -EINVAL; 155 + } 156 + 157 + msg[0].addr = client->addr; 158 + msg[0].flags = 0; 159 + msg[0].len = 5; 160 + msg[0].buf = wbuf; 161 + wbuf[0] = 5; 162 + wbuf[1] = M5MOLS_BYTE_READ; 163 + wbuf[2] = category; 164 + wbuf[3] = cmd; 165 + wbuf[4] = size; 166 + 167 + msg[1].addr = client->addr; 168 + msg[1].flags = I2C_M_RD; 169 + msg[1].len = size + 1; 170 + msg[1].buf = rbuf; 171 + 172 + /* minimum stabilization time */ 173 + usleep_range(200, 200); 174 + 175 + ret = i2c_transfer(client->adapter, msg, 2); 176 + if (ret < 0) { 177 + v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", 178 + size, category, cmd, ret); 179 + return ret; 180 + } 181 + 182 + *val = m5mols_swap_byte(&rbuf[1], size); 183 + 184 + return 0; 185 + } 186 + 187 + /** 188 + * m5mols_write - I2C command write function 189 + * @reg: combination of size, category and command for the I2C packet 190 + * @val: value to write 191 + */ 192 + int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) 193 + { 194 + struct i2c_client *client = v4l2_get_subdevdata(sd); 195 + u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; 196 + u8 category = I2C_CATEGORY(reg); 197 + u8 cmd = I2C_COMMAND(reg); 198 + u8 size = I2C_SIZE(reg); 199 + u32 *buf = (u32 *)&wbuf[4]; 200 + struct i2c_msg msg[1]; 201 + int ret; 202 + 203 + if (!client->adapter) 204 + return -ENODEV; 205 + 206 + if (size != 1 && size != 2 && size != 4) { 207 + v4l2_err(sd, "Wrong data size\n"); 208 + return -EINVAL; 209 + } 210 + 211 + msg->addr = client->addr; 212 + msg->flags = 0; 213 + msg->len = (u16)size + 4; 214 + msg->buf = wbuf; 215 + wbuf[0] = size + 4; 216 + wbuf[1] = M5MOLS_BYTE_WRITE; 217 + wbuf[2] = category; 218 + wbuf[3] = cmd; 219 + 220 + *buf = m5mols_swap_byte((u8 *)&val, size); 221 + 222 + usleep_range(200, 200); 223 + 224 + ret = i2c_transfer(client->adapter, msg, 1); 225 + if (ret < 0) { 226 + v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", 227 + size, category, cmd, ret); 228 + return ret; 229 + } 230 + 231 + return 0; 232 + } 233 + 234 + int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask) 235 + { 236 + u32 busy, i; 237 + int ret; 238 + 239 + for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { 240 + ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy); 241 + if (ret < 0) 242 + return ret; 243 + if ((busy & mask) == mask) 244 + return 0; 245 + } 246 + return -EBUSY; 247 + } 248 + 249 + /** 250 + * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts 251 + * 252 + * Before writing desired interrupt value the INT_FACTOR register should 253 + * be read to clear pending interrupts. 254 + */ 255 + int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg) 256 + { 257 + struct m5mols_info *info = to_m5mols(sd); 258 + u32 mask = is_available_af(info) ? REG_INT_AF : 0; 259 + u32 dummy; 260 + int ret; 261 + 262 + ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy); 263 + if (!ret) 264 + ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask); 265 + return ret; 266 + } 267 + 268 + /** 269 + * m5mols_reg_mode - Write the mode and check busy status 270 + * 271 + * It always accompanies a little delay changing the M-5MOLS mode, so it is 272 + * needed checking current busy status to guarantee right mode. 273 + */ 274 + static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode) 275 + { 276 + int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); 277 + 278 + return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); 279 + } 280 + 281 + /** 282 + * m5mols_mode - manage the M-5MOLS's mode 283 + * @mode: the required operation mode 284 + * 285 + * The commands of M-5MOLS are grouped into specific modes. Each functionality 286 + * can be guaranteed only when the sensor is operating in mode which which 287 + * a command belongs to. 288 + */ 289 + int m5mols_mode(struct m5mols_info *info, u32 mode) 290 + { 291 + struct v4l2_subdev *sd = &info->sd; 292 + int ret = -EINVAL; 293 + u32 reg; 294 + 295 + if (mode < REG_PARAMETER && mode > REG_CAPTURE) 296 + return ret; 297 + 298 + ret = m5mols_read(sd, SYSTEM_SYSMODE, &reg); 299 + if ((!ret && reg == mode) || ret) 300 + return ret; 301 + 302 + switch (reg) { 303 + case REG_PARAMETER: 304 + ret = m5mols_reg_mode(sd, REG_MONITOR); 305 + if (!ret && mode == REG_MONITOR) 306 + break; 307 + if (!ret) 308 + ret = m5mols_reg_mode(sd, REG_CAPTURE); 309 + break; 310 + 311 + case REG_MONITOR: 312 + if (mode == REG_PARAMETER) { 313 + ret = m5mols_reg_mode(sd, REG_PARAMETER); 314 + break; 315 + } 316 + 317 + ret = m5mols_reg_mode(sd, REG_CAPTURE); 318 + break; 319 + 320 + case REG_CAPTURE: 321 + ret = m5mols_reg_mode(sd, REG_MONITOR); 322 + if (!ret && mode == REG_MONITOR) 323 + break; 324 + if (!ret) 325 + ret = m5mols_reg_mode(sd, REG_PARAMETER); 326 + break; 327 + 328 + default: 329 + v4l2_warn(sd, "Wrong mode: %d\n", mode); 330 + } 331 + 332 + if (!ret) 333 + info->mode = mode; 334 + 335 + return ret; 336 + } 337 + 338 + /** 339 + * m5mols_get_version - retrieve full revisions information of M-5MOLS 340 + * 341 + * The version information includes revisions of hardware and firmware, 342 + * AutoFocus alghorithm version and the version string. 343 + */ 344 + static int m5mols_get_version(struct v4l2_subdev *sd) 345 + { 346 + struct m5mols_info *info = to_m5mols(sd); 347 + union { 348 + struct m5mols_version ver; 349 + u8 bytes[VERSION_SIZE]; 350 + } version; 351 + u32 *value; 352 + u8 cmd = CAT0_VER_CUSTOMER; 353 + int ret; 354 + 355 + do { 356 + value = (u32 *)&version.bytes[cmd]; 357 + ret = m5mols_read(sd, SYSTEM_CMD(cmd), value); 358 + if (ret) 359 + return ret; 360 + } while (cmd++ != CAT0_VER_AWB); 361 + 362 + do { 363 + value = (u32 *)&version.bytes[cmd]; 364 + ret = m5mols_read(sd, SYSTEM_VER_STRING, value); 365 + if (ret) 366 + return ret; 367 + if (cmd >= VERSION_SIZE - 1) 368 + return -EINVAL; 369 + } while (version.bytes[cmd++]); 370 + 371 + value = (u32 *)&version.bytes[cmd]; 372 + ret = m5mols_read(sd, AF_VERSION, value); 373 + if (ret) 374 + return ret; 375 + 376 + /* store version information swapped for being readable */ 377 + info->ver = version.ver; 378 + info->ver.fw = be16_to_cpu(info->ver.fw); 379 + info->ver.hw = be16_to_cpu(info->ver.hw); 380 + info->ver.param = be16_to_cpu(info->ver.param); 381 + info->ver.awb = be16_to_cpu(info->ver.awb); 382 + 383 + v4l2_info(sd, "Manufacturer\t[%s]\n", 384 + is_manufacturer(info, REG_SAMSUNG_ELECTRO) ? 385 + "Samsung Electro-Machanics" : 386 + is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 387 + "Samsung Fiber-Optics" : 388 + is_manufacturer(info, REG_SAMSUNG_TECHWIN) ? 389 + "Samsung Techwin" : "None"); 390 + v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n", 391 + info->ver.customer, info->ver.project); 392 + 393 + if (!is_available_af(info)) 394 + v4l2_info(sd, "No support Auto Focus on this firmware\n"); 395 + 396 + return ret; 397 + } 398 + 399 + /** 400 + * __find_restype - Lookup M-5MOLS resolution type according to pixel code 401 + * @code: pixel code 402 + */ 403 + static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code) 404 + { 405 + enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR; 406 + 407 + do { 408 + if (code == m5mols_default_ffmt[type].code) 409 + return type; 410 + } while (type++ != SIZE_DEFAULT_FFMT); 411 + 412 + return 0; 413 + } 414 + 415 + /** 416 + * __find_resolution - Lookup preset and type of M-5MOLS's resolution 417 + * @mf: pixel format to find/negotiate the resolution preset for 418 + * @type: M-5MOLS resolution type 419 + * @resolution: M-5MOLS resolution preset register value 420 + * 421 + * Find nearest resolution matching resolution preset and adjust mf 422 + * to supported values. 423 + */ 424 + static int __find_resolution(struct v4l2_subdev *sd, 425 + struct v4l2_mbus_framefmt *mf, 426 + enum m5mols_restype *type, 427 + u32 *resolution) 428 + { 429 + const struct m5mols_resolution *fsize = &m5mols_reg_res[0]; 430 + const struct m5mols_resolution *match = NULL; 431 + enum m5mols_restype stype = __find_restype(mf->code); 432 + int i = ARRAY_SIZE(m5mols_reg_res); 433 + unsigned int min_err = ~0; 434 + 435 + while (i--) { 436 + int err; 437 + if (stype == fsize->type) { 438 + err = abs(fsize->width - mf->width) 439 + + abs(fsize->height - mf->height); 440 + 441 + if (err < min_err) { 442 + min_err = err; 443 + match = fsize; 444 + } 445 + } 446 + fsize++; 447 + } 448 + if (match) { 449 + mf->width = match->width; 450 + mf->height = match->height; 451 + *resolution = match->reg; 452 + *type = stype; 453 + return 0; 454 + } 455 + 456 + return -EINVAL; 457 + } 458 + 459 + static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info, 460 + struct v4l2_subdev_fh *fh, 461 + enum v4l2_subdev_format_whence which, 462 + enum m5mols_restype type) 463 + { 464 + if (which == V4L2_SUBDEV_FORMAT_TRY) 465 + return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL; 466 + 467 + return &info->ffmt[type]; 468 + } 469 + 470 + static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, 471 + struct v4l2_subdev_format *fmt) 472 + { 473 + struct m5mols_info *info = to_m5mols(sd); 474 + struct v4l2_mbus_framefmt *format; 475 + 476 + if (fmt->pad != 0) 477 + return -EINVAL; 478 + 479 + format = __find_format(info, fh, fmt->which, info->res_type); 480 + if (!format) 481 + return -EINVAL; 482 + 483 + fmt->format = *format; 484 + return 0; 485 + } 486 + 487 + static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, 488 + struct v4l2_subdev_format *fmt) 489 + { 490 + struct m5mols_info *info = to_m5mols(sd); 491 + struct v4l2_mbus_framefmt *format = &fmt->format; 492 + struct v4l2_mbus_framefmt *sfmt; 493 + enum m5mols_restype type; 494 + u32 resolution = 0; 495 + int ret; 496 + 497 + if (fmt->pad != 0) 498 + return -EINVAL; 499 + 500 + ret = __find_resolution(sd, format, &type, &resolution); 501 + if (ret < 0) 502 + return ret; 503 + 504 + sfmt = __find_format(info, fh, fmt->which, type); 505 + if (!sfmt) 506 + return 0; 507 + 508 + *sfmt = m5mols_default_ffmt[type]; 509 + sfmt->width = format->width; 510 + sfmt->height = format->height; 511 + 512 + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { 513 + info->resolution = resolution; 514 + info->code = format->code; 515 + info->res_type = type; 516 + } 517 + 518 + return 0; 519 + } 520 + 521 + static int m5mols_enum_mbus_code(struct v4l2_subdev *sd, 522 + struct v4l2_subdev_fh *fh, 523 + struct v4l2_subdev_mbus_code_enum *code) 524 + { 525 + if (!code || code->index >= SIZE_DEFAULT_FFMT) 526 + return -EINVAL; 527 + 528 + code->code = m5mols_default_ffmt[code->index].code; 529 + 530 + return 0; 531 + } 532 + 533 + static struct v4l2_subdev_pad_ops m5mols_pad_ops = { 534 + .enum_mbus_code = m5mols_enum_mbus_code, 535 + .get_fmt = m5mols_get_fmt, 536 + .set_fmt = m5mols_set_fmt, 537 + }; 538 + 539 + /** 540 + * m5mols_sync_controls - Apply default scene mode and the current controls 541 + * 542 + * This is used only streaming for syncing between v4l2_ctrl framework and 543 + * m5mols's controls. First, do the scenemode to the sensor, then call 544 + * v4l2_ctrl_handler_setup. It can be same between some commands and 545 + * the scenemode's in the default v4l2_ctrls. But, such commands of control 546 + * should be prior to the scenemode's one. 547 + */ 548 + int m5mols_sync_controls(struct m5mols_info *info) 549 + { 550 + int ret = -EINVAL; 551 + 552 + if (!is_ctrl_synced(info)) { 553 + ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); 554 + if (ret) 555 + return ret; 556 + 557 + v4l2_ctrl_handler_setup(&info->handle); 558 + info->ctrl_sync = true; 559 + } 560 + 561 + return ret; 562 + } 563 + 564 + /** 565 + * m5mols_start_monitor - Start the monitor mode 566 + * 567 + * Before applying the controls setup the resolution and frame rate 568 + * in PARAMETER mode, and then switch over to MONITOR mode. 569 + */ 570 + static int m5mols_start_monitor(struct m5mols_info *info) 571 + { 572 + struct v4l2_subdev *sd = &info->sd; 573 + int ret; 574 + 575 + ret = m5mols_mode(info, REG_PARAMETER); 576 + if (!ret) 577 + ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution); 578 + if (!ret) 579 + ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30); 580 + if (!ret) 581 + ret = m5mols_mode(info, REG_MONITOR); 582 + if (!ret) 583 + ret = m5mols_sync_controls(info); 584 + 585 + return ret; 586 + } 587 + 588 + static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) 589 + { 590 + struct m5mols_info *info = to_m5mols(sd); 591 + 592 + if (enable) { 593 + int ret = -EINVAL; 594 + 595 + if (is_code(info->code, M5MOLS_RESTYPE_MONITOR)) 596 + ret = m5mols_start_monitor(info); 597 + if (is_code(info->code, M5MOLS_RESTYPE_CAPTURE)) 598 + ret = m5mols_start_capture(info); 599 + 600 + return ret; 601 + } 602 + 603 + return m5mols_mode(info, REG_PARAMETER); 604 + } 605 + 606 + static const struct v4l2_subdev_video_ops m5mols_video_ops = { 607 + .s_stream = m5mols_s_stream, 608 + }; 609 + 610 + static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) 611 + { 612 + struct v4l2_subdev *sd = to_sd(ctrl); 613 + struct m5mols_info *info = to_m5mols(sd); 614 + int ret; 615 + 616 + info->mode_save = info->mode; 617 + 618 + ret = m5mols_mode(info, REG_PARAMETER); 619 + if (!ret) 620 + ret = m5mols_set_ctrl(ctrl); 621 + if (!ret) 622 + ret = m5mols_mode(info, info->mode_save); 623 + 624 + return ret; 625 + } 626 + 627 + static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { 628 + .s_ctrl = m5mols_s_ctrl, 629 + }; 630 + 631 + static int m5mols_sensor_power(struct m5mols_info *info, bool enable) 632 + { 633 + struct v4l2_subdev *sd = &info->sd; 634 + struct i2c_client *client = v4l2_get_subdevdata(sd); 635 + const struct m5mols_platform_data *pdata = info->pdata; 636 + int ret; 637 + 638 + if (enable) { 639 + if (is_powered(info)) 640 + return 0; 641 + 642 + if (info->set_power) { 643 + ret = info->set_power(&client->dev, 1); 644 + if (ret) 645 + return ret; 646 + } 647 + 648 + ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); 649 + if (ret) { 650 + info->set_power(&client->dev, 0); 651 + return ret; 652 + } 653 + 654 + gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); 655 + usleep_range(1000, 1000); 656 + info->power = true; 657 + 658 + return ret; 659 + } 660 + 661 + if (!is_powered(info)) 662 + return 0; 663 + 664 + ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); 665 + if (ret) 666 + return ret; 667 + 668 + if (info->set_power) 669 + info->set_power(&client->dev, 0); 670 + 671 + gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); 672 + usleep_range(1000, 1000); 673 + info->power = false; 674 + 675 + return ret; 676 + } 677 + 678 + /* m5mols_update_fw - optional firmware update routine */ 679 + int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, 680 + int (*set_power)(struct m5mols_info *, bool)) 681 + { 682 + return 0; 683 + } 684 + 685 + /** 686 + * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. 687 + * 688 + * Booting internal ARM core makes the M-5MOLS is ready for getting commands 689 + * with I2C. It's the first thing to be done after it powered up. It must wait 690 + * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting. 691 + */ 692 + static int m5mols_sensor_armboot(struct v4l2_subdev *sd) 693 + { 694 + int ret; 695 + 696 + ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); 697 + if (ret < 0) 698 + return ret; 699 + 700 + msleep(520); 701 + 702 + ret = m5mols_get_version(sd); 703 + if (!ret) 704 + ret = m5mols_update_fw(sd, m5mols_sensor_power); 705 + if (ret) 706 + return ret; 707 + 708 + v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n"); 709 + 710 + ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); 711 + if (!ret) 712 + ret = m5mols_enable_interrupt(sd, REG_INT_AF); 713 + 714 + return ret; 715 + } 716 + 717 + static int m5mols_init_controls(struct m5mols_info *info) 718 + { 719 + struct v4l2_subdev *sd = &info->sd; 720 + u16 max_exposure; 721 + u16 step_zoom; 722 + int ret; 723 + 724 + /* Determine value's range & step of controls for various FW version */ 725 + ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure); 726 + if (!ret) 727 + step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1; 728 + if (ret) 729 + return ret; 730 + 731 + v4l2_ctrl_handler_init(&info->handle, 6); 732 + info->autowb = v4l2_ctrl_new_std(&info->handle, 733 + &m5mols_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, 734 + 0, 1, 1, 0); 735 + info->saturation = v4l2_ctrl_new_std(&info->handle, 736 + &m5mols_ctrl_ops, V4L2_CID_SATURATION, 737 + 1, 5, 1, 3); 738 + info->zoom = v4l2_ctrl_new_std(&info->handle, 739 + &m5mols_ctrl_ops, V4L2_CID_ZOOM_ABSOLUTE, 740 + 1, 70, step_zoom, 1); 741 + info->exposure = v4l2_ctrl_new_std(&info->handle, 742 + &m5mols_ctrl_ops, V4L2_CID_EXPOSURE, 743 + 0, max_exposure, 1, (int)max_exposure/2); 744 + info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, 745 + &m5mols_ctrl_ops, V4L2_CID_COLORFX, 746 + 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); 747 + info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, 748 + &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 749 + 1, 0, V4L2_EXPOSURE_MANUAL); 750 + 751 + sd->ctrl_handler = &info->handle; 752 + if (info->handle.error) { 753 + v4l2_err(sd, "Failed to initialize controls: %d\n", ret); 754 + v4l2_ctrl_handler_free(&info->handle); 755 + return info->handle.error; 756 + } 757 + 758 + v4l2_ctrl_cluster(2, &info->autoexposure); 759 + 760 + return 0; 761 + } 762 + 763 + /** 764 + * m5mols_s_power - Main sensor power control function 765 + * 766 + * To prevent breaking the lens when the sensor is powered off the Soft-Landing 767 + * algorithm is called where available. The Soft-Landing algorithm availability 768 + * dependends on the firmware provider. 769 + */ 770 + static int m5mols_s_power(struct v4l2_subdev *sd, int on) 771 + { 772 + struct m5mols_info *info = to_m5mols(sd); 773 + int ret; 774 + 775 + if (on) { 776 + ret = m5mols_sensor_power(info, true); 777 + if (!ret) 778 + ret = m5mols_sensor_armboot(sd); 779 + if (!ret) 780 + ret = m5mols_init_controls(info); 781 + if (ret) 782 + return ret; 783 + 784 + info->ffmt[M5MOLS_RESTYPE_MONITOR] = 785 + m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR]; 786 + info->ffmt[M5MOLS_RESTYPE_CAPTURE] = 787 + m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE]; 788 + return ret; 789 + } 790 + 791 + if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { 792 + ret = m5mols_mode(info, REG_MONITOR); 793 + if (!ret) 794 + ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); 795 + if (!ret) 796 + ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); 797 + if (!ret) 798 + ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS, 799 + REG_AF_IDLE); 800 + if (!ret) 801 + v4l2_info(sd, "Success soft-landing lens\n"); 802 + } 803 + 804 + ret = m5mols_sensor_power(info, false); 805 + if (!ret) { 806 + v4l2_ctrl_handler_free(&info->handle); 807 + info->ctrl_sync = false; 808 + } 809 + 810 + return ret; 811 + } 812 + 813 + static int m5mols_log_status(struct v4l2_subdev *sd) 814 + { 815 + struct m5mols_info *info = to_m5mols(sd); 816 + 817 + v4l2_ctrl_handler_log_status(&info->handle, sd->name); 818 + 819 + return 0; 820 + } 821 + 822 + static const struct v4l2_subdev_core_ops m5mols_core_ops = { 823 + .s_power = m5mols_s_power, 824 + .g_ctrl = v4l2_subdev_g_ctrl, 825 + .s_ctrl = v4l2_subdev_s_ctrl, 826 + .queryctrl = v4l2_subdev_queryctrl, 827 + .querymenu = v4l2_subdev_querymenu, 828 + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, 829 + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, 830 + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, 831 + .log_status = m5mols_log_status, 832 + }; 833 + 834 + static const struct v4l2_subdev_ops m5mols_ops = { 835 + .core = &m5mols_core_ops, 836 + .pad = &m5mols_pad_ops, 837 + .video = &m5mols_video_ops, 838 + }; 839 + 840 + static void m5mols_irq_work(struct work_struct *work) 841 + { 842 + struct m5mols_info *info = 843 + container_of(work, struct m5mols_info, work_irq); 844 + struct v4l2_subdev *sd = &info->sd; 845 + u32 reg; 846 + int ret; 847 + 848 + if (!is_powered(info) || 849 + m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt)) 850 + return; 851 + 852 + switch (info->interrupt & REG_INT_MASK) { 853 + case REG_INT_AF: 854 + if (!is_available_af(info)) 855 + break; 856 + ret = m5mols_read(sd, AF_STATUS, &reg); 857 + v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", 858 + reg == REG_AF_FAIL ? "Failed" : 859 + reg == REG_AF_SUCCESS ? "Success" : 860 + reg == REG_AF_IDLE ? "Idle" : "Busy"); 861 + break; 862 + case REG_INT_CAPTURE: 863 + if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags)) 864 + wake_up_interruptible(&info->irq_waitq); 865 + 866 + v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); 867 + break; 868 + default: 869 + v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); 870 + break; 871 + }; 872 + } 873 + 874 + static irqreturn_t m5mols_irq_handler(int irq, void *data) 875 + { 876 + struct v4l2_subdev *sd = data; 877 + struct m5mols_info *info = to_m5mols(sd); 878 + 879 + schedule_work(&info->work_irq); 880 + 881 + return IRQ_HANDLED; 882 + } 883 + 884 + static int __devinit m5mols_probe(struct i2c_client *client, 885 + const struct i2c_device_id *id) 886 + { 887 + const struct m5mols_platform_data *pdata = client->dev.platform_data; 888 + struct m5mols_info *info; 889 + struct v4l2_subdev *sd; 890 + int ret; 891 + 892 + if (pdata == NULL) { 893 + dev_err(&client->dev, "No platform data\n"); 894 + return -EINVAL; 895 + } 896 + 897 + if (!gpio_is_valid(pdata->gpio_reset)) { 898 + dev_err(&client->dev, "No valid RESET GPIO specified\n"); 899 + return -EINVAL; 900 + } 901 + 902 + if (!pdata->irq) { 903 + dev_err(&client->dev, "Interrupt not assigned\n"); 904 + return -EINVAL; 905 + } 906 + 907 + info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); 908 + if (!info) 909 + return -ENOMEM; 910 + 911 + info->pdata = pdata; 912 + info->set_power = pdata->set_power; 913 + 914 + ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST"); 915 + if (ret) { 916 + dev_err(&client->dev, "Failed to request gpio: %d\n", ret); 917 + goto out_free; 918 + } 919 + gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity); 920 + 921 + ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); 922 + if (ret) { 923 + dev_err(&client->dev, "Failed to get regulators: %d\n", ret); 924 + goto out_gpio; 925 + } 926 + 927 + sd = &info->sd; 928 + strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); 929 + v4l2_i2c_subdev_init(sd, client, &m5mols_ops); 930 + 931 + info->pad.flags = MEDIA_PAD_FL_SOURCE; 932 + ret = media_entity_init(&sd->entity, 1, &info->pad, 0); 933 + if (ret < 0) 934 + goto out_reg; 935 + sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; 936 + 937 + init_waitqueue_head(&info->irq_waitq); 938 + INIT_WORK(&info->work_irq, m5mols_irq_work); 939 + ret = request_irq(pdata->irq, m5mols_irq_handler, 940 + IRQF_TRIGGER_RISING, MODULE_NAME, sd); 941 + if (ret) { 942 + dev_err(&client->dev, "Interrupt request failed: %d\n", ret); 943 + goto out_me; 944 + } 945 + info->res_type = M5MOLS_RESTYPE_MONITOR; 946 + return 0; 947 + out_me: 948 + media_entity_cleanup(&sd->entity); 949 + out_reg: 950 + regulator_bulk_free(ARRAY_SIZE(supplies), supplies); 951 + out_gpio: 952 + gpio_free(pdata->gpio_reset); 953 + out_free: 954 + kfree(info); 955 + return ret; 956 + } 957 + 958 + static int __devexit m5mols_remove(struct i2c_client *client) 959 + { 960 + struct v4l2_subdev *sd = i2c_get_clientdata(client); 961 + struct m5mols_info *info = to_m5mols(sd); 962 + 963 + v4l2_device_unregister_subdev(sd); 964 + free_irq(info->pdata->irq, sd); 965 + 966 + regulator_bulk_free(ARRAY_SIZE(supplies), supplies); 967 + gpio_free(info->pdata->gpio_reset); 968 + media_entity_cleanup(&sd->entity); 969 + kfree(info); 970 + return 0; 971 + } 972 + 973 + static const struct i2c_device_id m5mols_id[] = { 974 + { MODULE_NAME, 0 }, 975 + { }, 976 + }; 977 + MODULE_DEVICE_TABLE(i2c, m5mols_id); 978 + 979 + static struct i2c_driver m5mols_i2c_driver = { 980 + .driver = { 981 + .name = MODULE_NAME, 982 + }, 983 + .probe = m5mols_probe, 984 + .remove = __devexit_p(m5mols_remove), 985 + .id_table = m5mols_id, 986 + }; 987 + 988 + static int __init m5mols_mod_init(void) 989 + { 990 + return i2c_add_driver(&m5mols_i2c_driver); 991 + } 992 + 993 + static void __exit m5mols_mod_exit(void) 994 + { 995 + i2c_del_driver(&m5mols_i2c_driver); 996 + } 997 + 998 + module_init(m5mols_mod_init); 999 + module_exit(m5mols_mod_exit); 1000 + 1001 + MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); 1002 + MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>"); 1003 + MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver"); 1004 + MODULE_LICENSE("GPL");
+399
drivers/media/video/m5mols/m5mols_reg.h
··· 1 + /* 2 + * Register map for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #ifndef M5MOLS_REG_H 17 + #define M5MOLS_REG_H 18 + 19 + #define M5MOLS_I2C_MAX_SIZE 4 20 + #define M5MOLS_BYTE_READ 0x01 21 + #define M5MOLS_BYTE_WRITE 0x02 22 + 23 + #define I2C_CATEGORY(__cat) ((__cat >> 16) & 0xff) 24 + #define I2C_COMMAND(__comm) ((__comm >> 8) & 0xff) 25 + #define I2C_SIZE(__reg_s) ((__reg_s) & 0xff) 26 + #define I2C_REG(__cat, __cmd, __reg_s) ((__cat << 16) | (__cmd << 8) | __reg_s) 27 + 28 + /* 29 + * Category section register 30 + * 31 + * The category means set including relevant command of M-5MOLS. 32 + */ 33 + #define CAT_SYSTEM 0x00 34 + #define CAT_PARAM 0x01 35 + #define CAT_MONITOR 0x02 36 + #define CAT_AE 0x03 37 + #define CAT_WB 0x06 38 + #define CAT_EXIF 0x07 39 + #define CAT_FD 0x09 40 + #define CAT_LENS 0x0a 41 + #define CAT_CAPT_PARM 0x0b 42 + #define CAT_CAPT_CTRL 0x0c 43 + #define CAT_FLASH 0x0f /* related to FW, revisions, booting */ 44 + 45 + /* 46 + * Category 0 - SYSTEM mode 47 + * 48 + * The SYSTEM mode in the M-5MOLS means area available to handle with the whole 49 + * & all-round system of sensor. It deals with version/interrupt/setting mode & 50 + * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by 51 + * packaging & manufacturer, even the customer and project code. And the 52 + * function details may vary among them. The version information helps to 53 + * determine what methods shall be used in the driver. 54 + * 55 + * There is many registers between customer version address and awb one. For 56 + * more specific contents, see definition if file m5mols.h. 57 + */ 58 + #define CAT0_VER_CUSTOMER 0x00 /* customer version */ 59 + #define CAT0_VER_AWB 0x09 /* Auto WB version */ 60 + #define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ 61 + #define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ 62 + #define CAT0_STATUS 0x0c /* SYSTEM mode status register */ 63 + #define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ 64 + #define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ 65 + 66 + #define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) 67 + #define REG_SYSINIT 0x00 /* SYSTEM mode */ 68 + #define REG_PARAMETER 0x01 /* PARAMETER mode */ 69 + #define REG_MONITOR 0x02 /* MONITOR mode */ 70 + #define REG_CAPTURE 0x03 /* CAPTURE mode */ 71 + 72 + #define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) 73 + #define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1) 74 + #define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ 75 + #define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ 76 + #define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ 77 + 78 + #define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1) 79 + #define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1) 80 + #define REG_INT_MODE (1 << 0) 81 + #define REG_INT_AF (1 << 1) 82 + #define REG_INT_ZOOM (1 << 2) 83 + #define REG_INT_CAPTURE (1 << 3) 84 + #define REG_INT_FRAMESYNC (1 << 4) 85 + #define REG_INT_FD (1 << 5) 86 + #define REG_INT_LENS_INIT (1 << 6) 87 + #define REG_INT_SOUND (1 << 7) 88 + #define REG_INT_MASK 0x0f 89 + 90 + /* 91 + * category 1 - PARAMETER mode 92 + * 93 + * This category supports function of camera features of M-5MOLS. It means we 94 + * can handle with preview(MONITOR) resolution size/frame per second/interface 95 + * between the sensor and the Application Processor/even the image effect. 96 + */ 97 + #define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */ 98 + #define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */ 99 + #define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */ 100 + #define CAT1_EFFECT 0x0b /* image effects */ 101 + 102 + #define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1) 103 + 104 + #define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1) 105 + #define REG_FPS_30 0x02 106 + 107 + #define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1) 108 + #define REG_INTERFACE_MIPI 0x02 109 + 110 + #define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1) 111 + #define REG_EFFECT_OFF 0x00 112 + #define REG_EFFECT_NEGA 0x01 113 + #define REG_EFFECT_EMBOSS 0x06 114 + #define REG_EFFECT_OUTLINE 0x07 115 + #define REG_EFFECT_WATERCOLOR 0x08 116 + 117 + /* 118 + * Category 2 - MONITOR mode 119 + * 120 + * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another 121 + * mode named "Preview", but this preview mode is used at the case specific 122 + * vider-recording mode. This mmode supports only YUYV format. On the other 123 + * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are 124 + * another options like zoom/color effect(different with effect in PARAMETER 125 + * mode)/anti hand shaking algorithm. 126 + */ 127 + #define CAT2_ZOOM 0x01 /* set the zoom position & execute */ 128 + #define CAT2_ZOOM_STEP 0x03 /* set the zoom step */ 129 + #define CAT2_CFIXB 0x09 /* CB value for color effect */ 130 + #define CAT2_CFIXR 0x0a /* CR value for color effect */ 131 + #define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */ 132 + #define CAT2_CHROMA_LVL 0x0f /* set chroma level */ 133 + #define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */ 134 + #define CAT2_EDGE_LVL 0x11 /* set sharpness level */ 135 + #define CAT2_EDGE_EN 0x12 /* set on/off sharpness */ 136 + #define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */ 137 + 138 + #define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1) 139 + 140 + #define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1) 141 + #define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1) 142 + #define REG_CFIXB_SEPIA 0xd8 143 + #define REG_CFIXR_SEPIA 0x18 144 + 145 + #define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1) 146 + #define REG_COLOR_EFFECT_OFF 0x00 147 + #define REG_COLOR_EFFECT_ON 0x01 148 + 149 + #define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1) 150 + #define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1) 151 + #define REG_CHROMA_OFF 0x00 152 + #define REG_CHROMA_ON 0x01 153 + 154 + #define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1) 155 + #define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1) 156 + #define REG_EDGE_OFF 0x00 157 + #define REG_EDGE_ON 0x01 158 + 159 + #define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1) 160 + 161 + /* 162 + * Category 3 - Auto Exposure 163 + * 164 + * The M-5MOLS exposure capbility is detailed as which is similar to digital 165 + * camera. This category supports AE locking/various AE mode(range of exposure) 166 + * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the 167 + * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be 168 + * different. So, this category also provide getting the max/min values. And, 169 + * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. 170 + */ 171 + #define CAT3_AE_LOCK 0x00 /* locking Auto exposure */ 172 + #define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */ 173 + #define CAT3_ISO 0x05 /* set ISO */ 174 + #define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */ 175 + #define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */ 176 + #define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */ 177 + #define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */ 178 + #define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */ 179 + #define CAT3_AE_INDEX 0x38 /* AE index */ 180 + 181 + #define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1) 182 + #define REG_AE_UNLOCK 0x00 183 + #define REG_AE_LOCK 0x01 184 + 185 + #define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1) 186 + #define REG_AE_OFF 0x00 /* AE off */ 187 + #define REG_AE_ALL 0x01 /* calc AE in all block integral */ 188 + #define REG_AE_CENTER 0x03 /* calc AE in center weighted */ 189 + #define REG_AE_SPOT 0x06 /* calc AE in specific spot */ 190 + 191 + #define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1) 192 + #define REG_ISO_AUTO 0x00 193 + #define REG_ISO_50 0x01 194 + #define REG_ISO_100 0x02 195 + #define REG_ISO_200 0x03 196 + #define REG_ISO_400 0x04 197 + #define REG_ISO_800 0x05 198 + 199 + #define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1) 200 + #define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1) 201 + #define REG_SCENE_NORMAL 0x00 202 + #define REG_SCENE_PORTRAIT 0x01 203 + #define REG_SCENE_LANDSCAPE 0x02 204 + #define REG_SCENE_SPORTS 0x03 205 + #define REG_SCENE_PARTY_INDOOR 0x04 206 + #define REG_SCENE_BEACH_SNOW 0x05 207 + #define REG_SCENE_SUNSET 0x06 208 + #define REG_SCENE_DAWN_DUSK 0x07 209 + #define REG_SCENE_FALL 0x08 210 + #define REG_SCENE_NIGHT 0x09 211 + #define REG_SCENE_AGAINST_LIGHT 0x0a 212 + #define REG_SCENE_FIRE 0x0b 213 + #define REG_SCENE_TEXT 0x0c 214 + #define REG_SCENE_CANDLE 0x0d 215 + 216 + #define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2) 217 + #define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2) 218 + #define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2) 219 + 220 + #define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1) 221 + #define REG_AE_INDEX_20_NEG 0x00 222 + #define REG_AE_INDEX_15_NEG 0x01 223 + #define REG_AE_INDEX_10_NEG 0x02 224 + #define REG_AE_INDEX_05_NEG 0x03 225 + #define REG_AE_INDEX_00 0x04 226 + #define REG_AE_INDEX_05_POS 0x05 227 + #define REG_AE_INDEX_10_POS 0x06 228 + #define REG_AE_INDEX_15_POS 0x07 229 + #define REG_AE_INDEX_20_POS 0x08 230 + 231 + /* 232 + * Category 6 - White Balance 233 + * 234 + * This category provide AWB locking/mode/preset/speed/gain bias, etc. 235 + */ 236 + #define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */ 237 + #define CAT6_AWB_MODE 0x02 /* set Auto or Manual */ 238 + #define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */ 239 + 240 + #define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1) 241 + #define REG_AWB_UNLOCK 0x00 242 + #define REG_AWB_LOCK 0x01 243 + 244 + #define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1) 245 + #define REG_AWB_AUTO 0x01 /* AWB off */ 246 + #define REG_AWB_PRESET 0x02 /* AWB preset */ 247 + 248 + #define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1) 249 + #define REG_AWB_INCANDESCENT 0x01 250 + #define REG_AWB_FLUORESCENT_1 0x02 251 + #define REG_AWB_FLUORESCENT_2 0x03 252 + #define REG_AWB_DAYLIGHT 0x04 253 + #define REG_AWB_CLOUDY 0x05 254 + #define REG_AWB_SHADE 0x06 255 + #define REG_AWB_HORIZON 0x07 256 + #define REG_AWB_LEDLIGHT 0x09 257 + 258 + /* 259 + * Category 7 - EXIF information 260 + */ 261 + #define CAT7_INFO_EXPTIME_NU 0x00 262 + #define CAT7_INFO_EXPTIME_DE 0x04 263 + #define CAT7_INFO_TV_NU 0x08 264 + #define CAT7_INFO_TV_DE 0x0c 265 + #define CAT7_INFO_AV_NU 0x10 266 + #define CAT7_INFO_AV_DE 0x14 267 + #define CAT7_INFO_BV_NU 0x18 268 + #define CAT7_INFO_BV_DE 0x1c 269 + #define CAT7_INFO_EBV_NU 0x20 270 + #define CAT7_INFO_EBV_DE 0x24 271 + #define CAT7_INFO_ISO 0x28 272 + #define CAT7_INFO_FLASH 0x2a 273 + #define CAT7_INFO_SDR 0x2c 274 + #define CAT7_INFO_QVAL 0x2e 275 + 276 + #define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4) 277 + #define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4) 278 + #define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4) 279 + #define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4) 280 + #define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4) 281 + #define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4) 282 + #define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4) 283 + #define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4) 284 + #define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4) 285 + #define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4) 286 + #define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2) 287 + #define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2) 288 + #define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2) 289 + #define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2) 290 + 291 + /* 292 + * Category 9 - Face Detection 293 + */ 294 + #define CAT9_FD_CTL 0x00 295 + 296 + #define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1) 297 + #define BIT_FD_EN 0 298 + #define BIT_FD_DRAW_FACE_FRAME 4 299 + #define BIT_FD_DRAW_SMILE_LVL 6 300 + #define REG_FD(shift) (1 << shift) 301 + #define REG_FD_OFF 0x0 302 + 303 + /* 304 + * Category A - Lens Parameter 305 + */ 306 + #define CATA_AF_MODE 0x01 307 + #define CATA_AF_EXECUTE 0x02 308 + #define CATA_AF_STATUS 0x03 309 + #define CATA_AF_VERSION 0x0a 310 + 311 + #define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1) 312 + #define REG_AF_NORMAL 0x00 /* Normal AF, one time */ 313 + #define REG_AF_MACRO 0x01 /* Macro AF, one time */ 314 + #define REG_AF_POWEROFF 0x07 315 + 316 + #define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1) 317 + #define REG_AF_STOP 0x00 318 + #define REG_AF_EXE_AUTO 0x01 319 + #define REG_AF_EXE_CAF 0x02 320 + 321 + #define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1) 322 + #define REG_AF_FAIL 0x00 323 + #define REG_AF_SUCCESS 0x02 324 + #define REG_AF_IDLE 0x04 325 + #define REG_AF_BUSY 0x05 326 + 327 + #define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1) 328 + 329 + /* 330 + * Category B - CAPTURE Parameter 331 + */ 332 + #define CATB_YUVOUT_MAIN 0x00 333 + #define CATB_MAIN_IMAGE_SIZE 0x01 334 + #define CATB_MCC_MODE 0x1d 335 + #define CATB_WDR_EN 0x2c 336 + #define CATB_LIGHT_CTRL 0x40 337 + #define CATB_FLASH_CTRL 0x41 338 + 339 + #define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1) 340 + #define REG_YUV422 0x00 341 + #define REG_BAYER10 0x05 342 + #define REG_BAYER8 0x06 343 + #define REG_JPEG 0x10 344 + 345 + #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1) 346 + 347 + #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1) 348 + #define REG_MCC_OFF 0x00 349 + #define REG_MCC_NORMAL 0x01 350 + 351 + #define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1) 352 + #define REG_WDR_OFF 0x00 353 + #define REG_WDR_ON 0x01 354 + #define REG_WDR_AUTO 0x02 355 + 356 + #define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1) 357 + #define REG_LIGHT_OFF 0x00 358 + #define REG_LIGHT_ON 0x01 359 + #define REG_LIGHT_AUTO 0x02 360 + 361 + #define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1) 362 + #define REG_FLASH_OFF 0x00 363 + #define REG_FLASH_ON 0x01 364 + #define REG_FLASH_AUTO 0x02 365 + 366 + /* 367 + * Category C - CAPTURE Control 368 + */ 369 + #define CATC_CAP_MODE 0x00 370 + #define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */ 371 + #define CATC_CAP_START 0x09 372 + #define CATC_CAP_IMAGE_SIZE 0x0d 373 + #define CATC_CAP_THUMB_SIZE 0x11 374 + 375 + #define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1) 376 + #define REG_CAP_NONE 0x00 377 + #define REG_CAP_ANTI_SHAKE 0x02 378 + 379 + #define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1) 380 + 381 + #define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1) 382 + #define REG_CAP_START_MAIN 0x01 383 + #define REG_CAP_START_THUMB 0x03 384 + 385 + #define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1) 386 + #define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1) 387 + 388 + /* 389 + * Category F - Flash 390 + * 391 + * This mode provides functions about internal flash stuff and system startup. 392 + */ 393 + #define CATF_CAM_START 0x12 /* It starts internal ARM core booting 394 + * after power-up */ 395 + 396 + #define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1) 397 + #define REG_START_ARM_BOOT 0x01 398 + 399 + #endif /* M5MOLS_REG_H */
+35
include/media/m5mols.h
··· 1 + /* 2 + * Driver header for M-5MOLS 8M Pixel camera sensor with ISP 3 + * 4 + * Copyright (C) 2011 Samsung Electronics Co., Ltd. 5 + * Author: HeungJun Kim, riverful.kim@samsung.com 6 + * 7 + * Copyright (C) 2009 Samsung Electronics Co., Ltd. 8 + * Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + */ 15 + 16 + #ifndef MEDIA_M5MOLS_H 17 + #define MEDIA_M5MOLS_H 18 + 19 + /** 20 + * struct m5mols_platform_data - platform data for M-5MOLS driver 21 + * @irq: GPIO getting the irq pin of M-5MOLS 22 + * @gpio_reset: GPIO driving the reset pin of M-5MOLS 23 + * @reset_polarity: active state for gpio_rst pin, 0 or 1 24 + * @set_power: an additional callback to the board setup code 25 + * to be called after enabling and before disabling 26 + * the sensor's supply regulators 27 + */ 28 + struct m5mols_platform_data { 29 + int irq; 30 + int gpio_reset; 31 + u8 reset_polarity; 32 + int (*set_power)(struct device *dev, int on); 33 + }; 34 + 35 + #endif /* MEDIA_M5MOLS_H */