Path: blob/master/drivers/media/video/m5mols/m5mols_capture.c
17782 views
/*1* The Capture code for Fujitsu M-5MOLS ISP2*3* Copyright (C) 2011 Samsung Electronics Co., Ltd.4* Author: HeungJun Kim <[email protected]>5*6* Copyright (C) 2009 Samsung Electronics Co., Ltd.7* Author: Dongsoo Nathaniel Kim <[email protected]>8*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*/1415#include <linux/i2c.h>16#include <linux/slab.h>17#include <linux/irq.h>18#include <linux/interrupt.h>19#include <linux/delay.h>20#include <linux/version.h>21#include <linux/gpio.h>22#include <linux/regulator/consumer.h>23#include <linux/videodev2.h>24#include <linux/version.h>25#include <media/v4l2-ctrls.h>26#include <media/v4l2-device.h>27#include <media/v4l2-subdev.h>28#include <media/m5mols.h>2930#include "m5mols.h"31#include "m5mols_reg.h"3233static int m5mols_capture_error_handler(struct m5mols_info *info,34int timeout)35{36int ret;3738/* Disable all interrupts and clear relevant interrupt staus bits */39ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE,40info->interrupt & ~(REG_INT_CAPTURE));41if (ret)42return ret;4344if (timeout == 0)45return -ETIMEDOUT;4647return 0;48}49/**50* m5mols_read_rational - I2C read of a rational number51*52* Read numerator and denominator from registers @addr_num and @addr_den53* respectively and return the division result in @val.54*/55static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,56u32 addr_den, u32 *val)57{58u32 num, den;5960int ret = m5mols_read_u32(sd, addr_num, &num);61if (!ret)62ret = m5mols_read_u32(sd, addr_den, &den);63if (ret)64return ret;65*val = den == 0 ? 0 : num / den;66return ret;67}6869/**70* m5mols_capture_info - Gather captured image information71*72* For now it gathers only EXIF information and file size.73*/74static int m5mols_capture_info(struct m5mols_info *info)75{76struct m5mols_exif *exif = &info->cap.exif;77struct v4l2_subdev *sd = &info->sd;78int ret;7980ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU,81EXIF_INFO_EXPTIME_DE, &exif->exposure_time);82if (ret)83return ret;84ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE,85&exif->shutter_speed);86if (ret)87return ret;88ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE,89&exif->aperture);90if (ret)91return ret;92ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE,93&exif->brightness);94if (ret)95return ret;96ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE,97&exif->exposure_bias);98if (ret)99return ret;100101ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed);102if (!ret)103ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash);104if (!ret)105ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr);106if (!ret)107ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval);108if (ret)109return ret;110111if (!ret)112ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main);113if (!ret)114ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb);115if (!ret)116info->cap.total = info->cap.main + info->cap.thumb;117118return ret;119}120121int m5mols_start_capture(struct m5mols_info *info)122{123struct v4l2_subdev *sd = &info->sd;124u8 resolution = info->resolution;125int timeout;126int ret;127128/*129* Preparing capture. Setting control & interrupt before entering130* capture mode131*132* 1) change to MONITOR mode for operating control & interrupt133* 2) set controls (considering v4l2_control value & lock 3A)134* 3) set interrupt135* 4) change to CAPTURE mode136*/137ret = m5mols_mode(info, REG_MONITOR);138if (!ret)139ret = m5mols_sync_controls(info);140if (!ret)141ret = m5mols_lock_3a(info, true);142if (!ret)143ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);144if (!ret)145ret = m5mols_mode(info, REG_CAPTURE);146if (!ret) {147/* Wait for capture interrupt, after changing capture mode */148timeout = wait_event_interruptible_timeout(info->irq_waitq,149test_bit(ST_CAPT_IRQ, &info->flags),150msecs_to_jiffies(2000));151if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags))152ret = m5mols_capture_error_handler(info, timeout);153}154if (!ret)155ret = m5mols_lock_3a(info, false);156if (ret)157return ret;158/*159* Starting capture. Setting capture frame count and resolution and160* the format(available format: JPEG, Bayer RAW, YUV).161*162* 1) select single or multi(enable to 25), format, size163* 2) set interrupt164* 3) start capture(for main image, now)165* 4) get information166* 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device)167*/168ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);169if (!ret)170ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);171if (!ret)172ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);173if (!ret)174ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);175if (!ret)176ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);177if (!ret) {178/* Wait for the capture completion interrupt */179timeout = wait_event_interruptible_timeout(info->irq_waitq,180test_bit(ST_CAPT_IRQ, &info->flags),181msecs_to_jiffies(2000));182if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) {183ret = m5mols_capture_info(info);184if (!ret)185v4l2_subdev_notify(sd, 0, &info->cap.total);186}187}188189return m5mols_capture_error_handler(info, timeout);190}191192193