linux/drivers/staging/media/omap4iss/iss.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * TI OMAP4 ISS V4L2 Driver
 *
 * Copyright (C) 2012, Texas Instruments
 *
 * Author: Sergio Aguirre <[email protected]>
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>

#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>

#include "iss.h"
#include "iss_regs.h"

#define ISS_PRINT_REGISTER(iss, name)

static void iss_print_status(struct iss_device *iss)
{}

/*
 * omap4iss_flush - Post pending L3 bus writes by doing a register readback
 * @iss: OMAP4 ISS device
 *
 * In order to force posting of pending writes, we need to write and
 * readback the same register, in this case the revision register.
 *
 * See this link for reference:
 *   https://www.mail-archive.com/[email protected]/msg08149.html
 */
static void omap4iss_flush(struct iss_device *iss)
{}

/*
 * iss_isp_enable_interrupts - Enable ISS ISP interrupts.
 * @iss: OMAP4 ISS device
 */
static void omap4iss_isp_enable_interrupts(struct iss_device *iss)
{}

/*
 * iss_isp_disable_interrupts - Disable ISS interrupts.
 * @iss: OMAP4 ISS device
 */
static void omap4iss_isp_disable_interrupts(struct iss_device *iss)
{}

/*
 * iss_enable_interrupts - Enable ISS interrupts.
 * @iss: OMAP4 ISS device
 */
static void iss_enable_interrupts(struct iss_device *iss)
{}

/*
 * iss_disable_interrupts - Disable ISS interrupts.
 * @iss: OMAP4 ISS device
 */
static void iss_disable_interrupts(struct iss_device *iss)
{}

int omap4iss_get_external_info(struct iss_pipeline *pipe,
			       struct media_link *link)
{}

/*
 * Configure the bridge. Valid inputs are
 *
 * IPIPEIF_INPUT_CSI2A: CSI2a receiver
 * IPIPEIF_INPUT_CSI2B: CSI2b receiver
 *
 * The bridge and lane shifter are configured according to the selected input
 * and the ISP platform data.
 */
void omap4iss_configure_bridge(struct iss_device *iss,
			       enum ipipeif_input_entity input)
{}

#ifdef ISS_ISR_DEBUG
static void iss_isr_dbg(struct iss_device *iss, u32 irqstatus)
{
	static const char * const name[] = {
		"ISP_0",
		"ISP_1",
		"ISP_2",
		"ISP_3",
		"CSIA",
		"CSIB",
		"CCP2_0",
		"CCP2_1",
		"CCP2_2",
		"CCP2_3",
		"CBUFF",
		"BTE",
		"SIMCOP_0",
		"SIMCOP_1",
		"SIMCOP_2",
		"SIMCOP_3",
		"CCP2_8",
		"HS_VS",
		"18",
		"19",
		"20",
		"21",
		"22",
		"23",
		"24",
		"25",
		"26",
		"27",
		"28",
		"29",
		"30",
		"31",
	};
	unsigned int i;

	dev_dbg(iss->dev, "ISS IRQ: ");

	for (i = 0; i < ARRAY_SIZE(name); i++) {
		if ((1 << i) & irqstatus)
			pr_cont("%s ", name[i]);
	}
	pr_cont("\n");
}

static void iss_isp_isr_dbg(struct iss_device *iss, u32 irqstatus)
{
	static const char * const name[] = {
		"ISIF_0",
		"ISIF_1",
		"ISIF_2",
		"ISIF_3",
		"IPIPEREQ",
		"IPIPELAST_PIX",
		"IPIPEDMA",
		"IPIPEBSC",
		"IPIPEHST",
		"IPIPEIF",
		"AEW",
		"AF",
		"H3A",
		"RSZ_REG",
		"RSZ_LAST_PIX",
		"RSZ_DMA",
		"RSZ_CYC_RZA",
		"RSZ_CYC_RZB",
		"RSZ_FIFO_OVF",
		"RSZ_FIFO_IN_BLK_ERR",
		"20",
		"21",
		"RSZ_EOF0",
		"RSZ_EOF1",
		"H3A_EOF",
		"IPIPE_EOF",
		"26",
		"IPIPE_DPC_INI",
		"IPIPE_DPC_RNEW0",
		"IPIPE_DPC_RNEW1",
		"30",
		"OCP_ERR",
	};
	unsigned int i;

	dev_dbg(iss->dev, "ISP IRQ: ");

	for (i = 0; i < ARRAY_SIZE(name); i++) {
		if ((1 << i) & irqstatus)
			pr_cont("%s ", name[i]);
	}
	pr_cont("\n");
}
#endif

/*
 * iss_isr - Interrupt Service Routine for ISS module.
 * @irq: Not used currently.
 * @_iss: Pointer to the OMAP4 ISS device
 *
 * Handles the corresponding callback if plugged in.
 *
 * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
 * IRQ wasn't handled.
 */
static irqreturn_t iss_isr(int irq, void *_iss)
{}

static const struct media_device_ops iss_media_ops =;

/* -----------------------------------------------------------------------------
 * Pipeline stream management
 */

/*
 * iss_pipeline_disable - Disable streaming on a pipeline
 * @pipe: ISS pipeline
 * @until: entity at which to stop pipeline walk
 *
 * Walk the entities chain starting at the pipeline output video node and stop
 * all modules in the chain. Wait synchronously for the modules to be stopped if
 * necessary.
 *
 * If the until argument isn't NULL, stop the pipeline walk when reaching the
 * until entity. This is used to disable a partially started pipeline due to a
 * subdev start error.
 */
static int iss_pipeline_disable(struct iss_pipeline *pipe,
				struct media_entity *until)
{}

/*
 * iss_pipeline_enable - Enable streaming on a pipeline
 * @pipe: ISS pipeline
 * @mode: Stream mode (single shot or continuous)
 *
 * Walk the entities chain starting at the pipeline output video node and start
 * all modules in the chain in the given mode.
 *
 * Return 0 if successful, or the return value of the failed video::s_stream
 * operation otherwise.
 */
static int iss_pipeline_enable(struct iss_pipeline *pipe,
			       enum iss_pipeline_stream_state mode)
{}

/*
 * omap4iss_pipeline_set_stream - Enable/disable streaming on a pipeline
 * @pipe: ISS pipeline
 * @state: Stream state (stopped, single shot or continuous)
 *
 * Set the pipeline to the given stream state. Pipelines can be started in
 * single-shot or continuous mode.
 *
 * Return 0 if successful, or the return value of the failed video::s_stream
 * operation otherwise. The pipeline state is not updated when the operation
 * fails, except when stopping the pipeline.
 */
int omap4iss_pipeline_set_stream(struct iss_pipeline *pipe,
				 enum iss_pipeline_stream_state state)
{}

/*
 * omap4iss_pipeline_cancel_stream - Cancel stream on a pipeline
 * @pipe: ISS pipeline
 *
 * Cancelling a stream mark all buffers on all video nodes in the pipeline as
 * erroneous and makes sure no new buffer can be queued. This function is called
 * when a fatal error that prevents any further operation on the pipeline
 * occurs.
 */
void omap4iss_pipeline_cancel_stream(struct iss_pipeline *pipe)
{}

/*
 * iss_pipeline_is_last - Verify if entity has an enabled link to the output
 *			  video node
 * @me: ISS module's media entity
 *
 * Returns 1 if the entity has an enabled link to the output video node or 0
 * otherwise. It's true only while pipeline can have no more than one output
 * node.
 */
static int iss_pipeline_is_last(struct media_entity *me)
{}

static int iss_reset(struct iss_device *iss)
{}

static int iss_isp_reset(struct iss_device *iss)
{}

/*
 * iss_module_sync_idle - Helper to sync module with its idle state
 * @me: ISS submodule's media entity
 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
 * @stopping: flag which tells module wants to stop
 *
 * This function checks if ISS submodule needs to wait for next interrupt. If
 * yes, makes the caller to sleep while waiting for such event.
 */
int omap4iss_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
			      atomic_t *stopping)
{}

/*
 * omap4iss_module_sync_is_stopped - Helper to verify if module was stopping
 * @wait: ISS submodule's wait queue for streamoff/interrupt synchronization
 * @stopping: flag which tells module wants to stop
 *
 * This function checks if ISS submodule was stopping. In case of yes, it
 * notices the caller by setting stopping to 0 and waking up the wait queue.
 * Returns 1 if it was stopping or 0 otherwise.
 */
int omap4iss_module_sync_is_stopping(wait_queue_head_t *wait,
				     atomic_t *stopping)
{}

/* --------------------------------------------------------------------------
 * Clock management
 */

#define ISS_CLKCTRL_MASK

static int __iss_subclk_update(struct iss_device *iss)
{}

int omap4iss_subclk_enable(struct iss_device *iss,
			   enum iss_subclk_resource res)
{}

int omap4iss_subclk_disable(struct iss_device *iss,
			    enum iss_subclk_resource res)
{}

#define ISS_ISP5_CLKCTRL_MASK

static void __iss_isp_subclk_update(struct iss_device *iss)
{}

void omap4iss_isp_subclk_enable(struct iss_device *iss,
				enum iss_isp_subclk_resource res)
{}

void omap4iss_isp_subclk_disable(struct iss_device *iss,
				 enum iss_isp_subclk_resource res)
{}

/*
 * iss_enable_clocks - Enable ISS clocks
 * @iss: OMAP4 ISS device
 *
 * Return 0 if successful, or clk_enable return value if any of tthem fails.
 */
static int iss_enable_clocks(struct iss_device *iss)
{}

/*
 * iss_disable_clocks - Disable ISS clocks
 * @iss: OMAP4 ISS device
 */
static void iss_disable_clocks(struct iss_device *iss)
{}

static int iss_get_clocks(struct iss_device *iss)
{}

/*
 * omap4iss_get - Acquire the ISS resource.
 *
 * Initializes the clocks for the first acquire.
 *
 * Increment the reference count on the ISS. If the first reference is taken,
 * enable clocks and power-up all submodules.
 *
 * Return a pointer to the ISS device structure, or NULL if an error occurred.
 */
struct iss_device *omap4iss_get(struct iss_device *iss)
{}

/*
 * omap4iss_put - Release the ISS
 *
 * Decrement the reference count on the ISS. If the last reference is released,
 * power-down all submodules, disable clocks and free temporary buffers.
 */
void omap4iss_put(struct iss_device *iss)
{}

static int iss_map_mem_resource(struct platform_device *pdev,
				struct iss_device *iss,
				enum iss_mem_resources res)
{}

static void iss_unregister_entities(struct iss_device *iss)
{}

/*
 * iss_register_subdev_group - Register a group of subdevices
 * @iss: OMAP4 ISS device
 * @board_info: I2C subdevs board information array
 *
 * Register all I2C subdevices in the board_info array. The array must be
 * terminated by a NULL entry, and the first entry must be the sensor.
 *
 * Return a pointer to the sensor media entity if it has been successfully
 * registered, or NULL otherwise.
 */
static struct v4l2_subdev *
iss_register_subdev_group(struct iss_device *iss,
			  struct iss_subdev_i2c_board_info *board_info)
{}

static int iss_register_entities(struct iss_device *iss)
{}

/*
 * iss_create_links() - Pads links creation for the subdevices
 * @iss : Pointer to ISS device
 *
 * return negative error code or zero on success
 */
static int iss_create_links(struct iss_device *iss)
{
	int ret;

	ret = omap4iss_csi2_create_links(iss);
	if (ret < 0) {
		dev_err(iss->dev, "CSI2 pads links creation failed\n");
		return ret;
	}

	ret = omap4iss_ipipeif_create_links(iss);
	if (ret < 0) {
		dev_err(iss->dev, "ISP IPIPEIF pads links creation failed\n");
		return ret;
	}

	ret = omap4iss_resizer_create_links(iss);
	if (ret < 0) {
		dev_err(iss->dev, "ISP RESIZER pads links creation failed\n");
		return ret;
	}

	/* Connect the submodules. */
	ret = media_create_pad_link(
			&iss->csi2a.subdev.entity, CSI2_PAD_SOURCE,
			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
	if (ret < 0)
		return ret;

	ret = media_create_pad_link(
			&iss->csi2b.subdev.entity, CSI2_PAD_SOURCE,
			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SINK, 0);
	if (ret < 0)
		return ret;

	ret = media_create_pad_link(
			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
	if (ret < 0)
		return ret;

	ret = media_create_pad_link(
			&iss->ipipeif.subdev.entity, IPIPEIF_PAD_SOURCE_VP,
			&iss->ipipe.subdev.entity, IPIPE_PAD_SINK, 0);
	if (ret < 0)
		return ret;

	ret = media_create_pad_link(
			&iss->ipipe.subdev.entity, IPIPE_PAD_SOURCE_VP,
			&iss->resizer.subdev.entity, RESIZER_PAD_SINK, 0);
	if (ret < 0)
		return ret;

	return 0;
};

static void iss_cleanup_modules(struct iss_device *iss)
{}

static int iss_initialize_modules(struct iss_device *iss)
{}

static int iss_probe(struct platform_device *pdev)
{}

static void iss_remove(struct platform_device *pdev)
{}

static const struct platform_device_id omap4iss_id_table[] =;
MODULE_DEVICE_TABLE(platform, omap4iss_id_table);

static struct platform_driver iss_driver =;

module_platform_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();