/drivers/media/video/m5mols/m5mols_capture.c
C | 191 lines | 129 code | 15 blank | 47 comment | 33 complexity | 4378563f31cfa6846871b7185dfb3a09 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
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 34static 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 */ 56static 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_u32(sd, addr_num, &num); 62 if (!ret) 63 ret = m5mols_read_u32(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 */ 75static 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_u16(sd, EXIF_INFO_ISO, &exif->iso_speed); 103 if (!ret) 104 ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash); 105 if (!ret) 106 ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr); 107 if (!ret) 108 ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval); 109 if (ret) 110 return ret; 111 112 if (!ret) 113 ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main); 114 if (!ret) 115 ret = m5mols_read_u32(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 122int m5mols_start_capture(struct m5mols_info *info) 123{ 124 struct v4l2_subdev *sd = &info->sd; 125 u8 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}