blob: 9a801daca96d3502023b5ecbdcbdf89fc8c08cc3 [file] [log] [blame]
/*
* Copyright (C) 2017 Intel Corporation
* Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "SensorHwOp"
#include "SensorHwOp.h"
namespace android {
namespace camera2 {
/**
* SENSOR TYPE OPERATIONS
*/
/**
* Base sensor class operation
* also SMIAPP sensor class operation
*/
SensorHwOp::SensorHwOp(std::shared_ptr<V4L2Subdevice> pixelArraySubdev):
pPixelArraySubdev(pixelArraySubdev),
pPixelRate(0),
pHorzBlank(0),
pVertBlank(0),
pCropWidth(0),
pCropHeight(0),
pSensorFTWidth(0),
pSensorFTHeight(0),
pHBlankReadOnly(false),
pVBlankReadOnly(false)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1);
}
SensorHwOp::~SensorHwOp()
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1);
}
/************* V4L2 wrapper *******************/
/**
* retrieving crop values and format from pixel array driver.
*
* \param[OUT] width: width of the crop
* \param[OUT] height: height of the crop
* \param[OUT] code: pixel format
*
* \return IOCTL return value.
*/
int SensorHwOp::getActivePixelArraySize(int &width,
int &height,
int &code)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int status = BAD_VALUE;
status = pPixelArraySubdev->getPadFormat(0, width, height, code);
return status;
}
/**
* Update the class members used to calculate blanking
*
* \return IOCTL return value.
*/
status_t SensorHwOp::updateMembers()
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int status = BAD_VALUE;
int code = 0;
v4l2_queryctrl control;
status = getActivePixelArraySize(pCropWidth, pCropHeight, code);
if (status != NO_ERROR) {
LOGE("Error getting PA size");
return UNKNOWN_ERROR;
}
status = updateFrameTimings();
if (status != NO_ERROR) {
LOGE("Error updating frame timings");
return UNKNOWN_ERROR;
}
control.id = V4L2_CID_HBLANK;
status = pPixelArraySubdev->queryControl(control);
if (status == NO_ERROR && (control.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
pHBlankReadOnly = true;
LOG1("HBLANK is readonly");
}
control.id = V4L2_CID_VBLANK;
status = pPixelArraySubdev->queryControl(control);
if (status == NO_ERROR && (control.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
pVBlankReadOnly = true;
LOG1("VBLANK is readonly");
}
return status;
}
/**
* retrieving output size and format from sensor
* after possible cropping, binning and scaling
*
* \param[OUT] width: width of the crop
* \param[OUT] height: height of the crop
* \param[OUT] code: pixel format
*
* \return IOCTL return value.
*/
int SensorHwOp::getSensorOutputSize(int &width, int &height, int &code)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int status = BAD_VALUE;
status = pPixelArraySubdev->getPadFormat(0, width, height, code);
return status;
}
/**
* retrieving pixel rate from pixel array
*
* \param[OUT] pixel_rate: pixel rate value
*
* \return IOCTL return value.
*/
int SensorHwOp::getPixelRate(int &pixel_rate)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
return pPixelArraySubdev->getControl(V4L2_CID_PIXEL_RATE, &pixel_rate);
}
/**
* retrieving link frequency from scaler subdev
*
* \param[OUT] link_freq: link frequency value
*
* \return IOCTL return value.
*/
int SensorHwOp::getLinkFreq(int &link_freq)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
return pPixelArraySubdev->getControl(V4L2_CID_LINK_FREQ, &link_freq);
}
/**
* retrieving pixel clock from scaler subdev
*
* \param[OUT] pixel_clock: pixel clock value
*
* \return IOCTL return value.
*/
int SensorHwOp::getPixelClock(int64_t &pixel_clock)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int ret = BAD_VALUE;
int link_freq = 0;
v4l2_querymenu menu;
CLEAR(menu);
ret = pPixelArraySubdev->getControl(V4L2_CID_LINK_FREQ, &link_freq);
if (ret != NO_ERROR)
return ret;
menu.id = V4L2_CID_LINK_FREQ;
menu.index = link_freq;
ret = pPixelArraySubdev->queryMenu(menu);
if (ret != NO_ERROR)
return ret;
pixel_clock = menu.value;
LOG1("pixel clock set to %lld", menu.value);
return ret;
}
/**
* set exposure value to sensor driver
*
* \param[IN] coarse_exposure: coarse exposure value
* \param[IN] fine_exposure: fine exposure value
*
* return IOCTL return value.
*/
int SensorHwOp::setExposure(int coarse_exposure, int fine_exposure)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
UNUSED(fine_exposure);
int ret = BAD_VALUE;
ret = pPixelArraySubdev->setControl(V4L2_CID_EXPOSURE,
coarse_exposure, "Exposure Time");
// TODO: Need fine_exposure whenever supported on kernel.
return ret;
}
/**
* get exposure value from sensor driver
*
* \param[OUT] coarse_exposure: coarse exposure value
* \param[OUT] fine_exposure: fine exposure value
*
* TODO: V4L2 does not support FINE_EXPOSURE setting
*
* \return IOCTL return value.
*/
int SensorHwOp::getExposure(int &coarse_exposure, int &fine_exposure)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int ret = BAD_VALUE;
ret = pPixelArraySubdev->getControl(V4L2_CID_EXPOSURE, &coarse_exposure);
// TODO: Need fine exposure whenever supported in kernel.
fine_exposure = -1;
return ret;
}
/**
* get exposure range value from sensor driver
*
* \param[OUT] coarse_exposure: exposure min value
* \param[OUT] fine_exposure: exposure max value
* \param[OUT] exposure_step: step of exposure
*
* TODO: V4L2 does not support FINE_EXPOSURE setting
*
* \return IOCTL return value.
*/
int SensorHwOp::getExposureRange(int &exposure_min, int &exposure_max, int &exposure_step)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int ret = BAD_VALUE;
v4l2_queryctrl exposure;
CLEAR(exposure);
exposure.id = V4L2_CID_EXPOSURE;
ret = pPixelArraySubdev->queryControl(exposure);
if (ret != NO_ERROR) {
LOGE("Couldn't get exposure Range");
return ret;
}
exposure_min = exposure.minimum;
exposure_max = exposure.maximum;
exposure_step = exposure.step;
return ret;
}
/**
* set analog and digital gain to sensor driver
*
* \param[IN] analog_gain: analog gain value
* \param[IN] digital_gain: digital gain value
*
* \return IOCTL return value.
*/
int SensorHwOp::setGains(int analog_gain, int digital_gain)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int ret = BAD_VALUE;
ret = pPixelArraySubdev->setControl(V4L2_CID_ANALOGUE_GAIN,
analog_gain, "Analog Gain");
if (digital_gain != 0) {
ret = pPixelArraySubdev->setControl(V4L2_CID_DIGITAL_GAIN,
digital_gain, "Digital Gain");
}
return ret;
}
/**
* get analog and digital gain from sensor driver
*
* \param[OUT] analog_gain: analog gain value
* \param[OUT] digital_gain: digital gain value
*
* TODO: V4L2 does not support DIGITAL_GAIN setting
*
* return IOCTL return value.
*/
int SensorHwOp::getGains(int &analog_gain, int &digital_gain)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
int ret = BAD_VALUE;
ret = pPixelArraySubdev->getControl(V4L2_CID_ANALOGUE_GAIN, &analog_gain);
// XXX: Need digital_gain whenever defined in V4L2.
digital_gain = -1;
return ret;
}
/**
* This function is using Hblank and Vblank, because it s supported
* by both CRL and SMIAPP drivers
*
* \param[IN] llp: Line Length in Pixel value
* \param[IN] fll: Frame Length in Line value
*
* \return IOCTL return value.
*/
status_t SensorHwOp::setFrameDuration(unsigned int llp, unsigned int fll)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
status_t status = OK;
status_t statusH = OK;
status_t statusV = OK;
int horzBlank, vertBlank;
/* only calculate when not 0 */
if (llp && !pHBlankReadOnly) {
horzBlank = llp - pCropWidth;
statusH = pPixelArraySubdev->setControl(V4L2_CID_HBLANK,
horzBlank, "Horizontal Blanking");
if (statusH != OK)
LOGE("Failed to set hblank");
}
if (fll && !pVBlankReadOnly) {
vertBlank = fll - pCropHeight;
statusV = pPixelArraySubdev->setControl(V4L2_CID_VBLANK,
vertBlank, "Vertical Blanking");
if (statusV != OK)
LOGE("Failed to set vblank");
}
if (statusH != OK || statusV != OK)
status = UNKNOWN_ERROR;
return status;
}
/**
* This function is using Hblank and Vblank, because it s supported
* by both CRL and SMIAPP drivers
*
* \param[OUT] llp: Line Length in Pixel value
* \param[OUT] fll: Frame Length in Line value
*
* \return IOCTL return value.
*/
status_t SensorHwOp::getMinimumFrameDuration(unsigned int &llp, unsigned int &fll)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
status_t status = OK;
status_t statusH = OK;
status_t statusV = OK;
int horzBlank, vertBlank;
// Get query control for sensor mode to determine min value
v4l2_queryctrl sensorModeControl;
CLEAR(sensorModeControl);
sensorModeControl.id = V4L2_CID_HBLANK;
statusH = pPixelArraySubdev->queryControl(sensorModeControl);
horzBlank = sensorModeControl.minimum;
LOG2("%s, queryControl statusH: %d, horzBlank: %d", __FUNCTION__, statusH, horzBlank);
if (statusH == OK)
llp = horzBlank + pCropWidth;
else
LOGE("failed to get hblank");
CLEAR(sensorModeControl);
sensorModeControl.id = V4L2_CID_VBLANK;
statusV = pPixelArraySubdev->queryControl(sensorModeControl);
vertBlank = sensorModeControl.minimum;
LOG2("%s, queryControl statusV: %d, vertBlank, %d", __FUNCTION__, statusV, vertBlank);
if (statusV == OK)
fll = vertBlank + pCropHeight;
else
LOGE("failed to get vblank");
if (statusH != OK || statusV != OK)
status = UNKNOWN_ERROR;
pHorzBlank = horzBlank;
pVertBlank = vertBlank;
return status;
}
/**
* This function is used to get vblank from private member
*
* \param[OUT] vblank: local vblank value
*
* \return OK
*/
int SensorHwOp::getVBlank(unsigned int &vblank)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
vblank = pVertBlank;
return OK;
}
/**
* This function is used to get hblank from private member
*
* \param[OUT] hblank: local hblank value
*
* \return OK
*/
int SensorHwOp::getHBlank(unsigned int &hblank)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
hblank = pHorzBlank;
return OK;
}
/**
* This function is used to get the aperture from driver
*
* \param[OUT] aperture: aperture from driver
*
* \return IOCTL return value
*/
int SensorHwOp::getAperture(int &aperture)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
return pPixelArraySubdev->getControl(V4L2_CID_IRIS_ABSOLUTE, &aperture);
}
/**
* This function is empty for base class
*
* \return OK.
*/
status_t SensorHwOp::updateFrameTimings()
{
return OK;
}
/**
* Set the sensor frame timings from the xml
*
* \param[IN] width: Frame timing width
* \param[IN] height: Frame timing height
*
* \return OK
*/
status_t SensorHwOp::setSensorFT(int width, int height)
{
HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2);
pSensorFTWidth = width;
pSensorFTHeight = height;
LOG2("@%s: Setting sensor FT %d %d", __FUNCTION__, pSensorFTWidth,
pSensorFTHeight);
return OK;
}
/**
* retrieving test pattern mode from sensor driver
*
* \param[OUT] mode: sensor test pattern mode
* 0: TEST_PATTERN_MODE_OFF
* 1: TEST_PATTERN_MODE_COLOR_BARS
* 2: TEST_PATTERN_MODE_DEFAULT
*
* \return IOCTL return value.
*/
int SensorHwOp::getTestPattern(int *mode)
{
return pPixelArraySubdev->getControl(V4L2_CID_TEST_PATTERN, mode);
}
/**
* set test pattern mode to sensor driver
*
* \param[IN] mode: test pattern mode
* 0: TEST_PATTERN_MODE_OFF
* 1: TEST_PATTERN_MODE_COLOR_BARS
* 2: TEST_PATTERN_MODE_DEFAULT
*
* \return IOCTL return value.
*/
int SensorHwOp::setTestPattern(int mode)
{
return pPixelArraySubdev->setControl(V4L2_CID_TEST_PATTERN,
mode, "Test Pattern");
}
/*
* -- end SensorHwOp
*/
}// namespace camera2
}// namespace android