/*
* Greybus Camera protocol driver.
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include "gb-camera.h"
#include "greybus.h"
#include "greybus_protocols.h"
enum gb_camera_debugs_buffer_id {
GB_CAMERA_DEBUGFS_BUFFER_CAPABILITIES,
GB_CAMERA_DEBUGFS_BUFFER_STREAMS,
GB_CAMERA_DEBUGFS_BUFFER_CAPTURE,
GB_CAMERA_DEBUGFS_BUFFER_FLUSH,
GB_CAMERA_DEBUGFS_BUFFER_MAX,
};
struct gb_camera_debugfs_buffer {
char data[PAGE_SIZE];
size_t length;
};
enum gb_camera_state {
GB_CAMERA_STATE_UNCONFIGURED,
GB_CAMERA_STATE_CONFIGURED,
};
/**
* struct gb_camera - A Greybus Camera Device
* @connection: the greybus connection for camera management
* @data_connection: the greybus connection for camera data
* @data_cport_id: the data CPort ID on the module side
* @mutex: protects the connection and state fields
* @state: the current module state
* @debugfs: debugfs entries for camera protocol operations testing
* @module: Greybus camera module registered to HOST processor.
*/
struct gb_camera {
struct gb_bundle *bundle;
struct gb_connection *connection;
struct gb_connection *data_connection;
u16 data_cport_id;
struct mutex mutex;
enum gb_camera_state state;
struct {
struct dentry *root;
struct gb_camera_debugfs_buffer *buffers;
} debugfs;
struct gb_camera_module module;
};
struct gb_camera_stream_config {
unsigned int width;
unsigned int height;
unsigned int format;
unsigned int vc;
unsigned int dt[2];
unsigned int max_size;
};
struct gb_camera_fmt_map {
enum v4l2_mbus_pixelcode mbus_code;
unsigned int gb_format;
};
/* GB format to media code map */
static const struct gb_camera_fmt_map mbus_to_gbus_format[] = {
{
.mbus_code = V4L2_MBUS_FMT_UYVY8_1X16,
.gb_format = 0x01,
},
{
.mbus_code = V4L2_MBUS_FMT_NV12_1x8,
.gb_format = 0x12,
},
{
.mbus_code = V4L2_MBUS_FMT_NV21_1x8,
.gb_format = 0x13,
},
{
.mbus_code = V4L2_MBUS_FMT_YU12_1x8,
.gb_format = 0x16,
},
{
.mbus_code = V4L2_MBUS_FMT_YV12_1x8,
.gb_format = 0x17,
},
{
.mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
.gb_format = 0x40,
},
{
.mbus_code = V4L2_MBUS_FMT_ARA_METADATA_1X8,
.gb_format = 0x41,
},
{
.mbus_code = V4L2_MBUS_FMT_ARA_DEBUG_DATA_1X8,
.gb_format = 0x42,
},
};
#define ES2_APB_CDSI0_CPORT 16
#define ES2_APB_CDSI1_CPORT 17
#define GB_CAMERA_MAX_SETTINGS_SIZE 8192
#define gcam_dbg(gcam, format...) dev_dbg(&gcam->bundle->dev, format)
#define gcam_info(gcam, format...) dev_info(&gcam->bundle->dev, format)
#define gcam_err(gcam, format...) dev_err(&gcam->bundle->dev, format)
/* -----------------------------------------------------------------------------
* Hardware Configuration
*/
static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id,
bool hs)
{
struct gb_svc *svc = gcam->connection->hd->svc;
int ret;
if (hs)
ret = gb_svc_intf_set_power_mode(svc, intf_id,
GB_SVC_UNIPRO_HS_SERIES_A,
GB_SVC_UNIPRO_FAST_MODE, 2, 2,
GB_SVC_SMALL_AMPLITUDE,
GB_SVC_NO_DE_EMPHASIS,
GB_SVC_UNIPRO_FAST_MODE, 2, 2,
GB_SVC_PWRM_RXTERMINATION |
GB_SVC_PWRM_TXTERMINATION, 0,
NULL, NULL);
else
ret = gb_svc_intf_set_power_mode(svc, intf_id,
GB_SVC_UNIPRO_HS_SERIES_A,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
2, 1,
GB_SVC_SMALL_AMPLITUDE,
GB_SVC_NO_DE_EMPHASIS,
GB_SVC_UNIPRO_SLOW_AUTO_MODE,
2