PageRenderTime 28ms CodeModel.GetById 19ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/media/video/m5mols/m5mols_capture.c

https://bitbucket.org/wisechild/galaxy-nexus
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}