cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

xilinx-vip.c (9449B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Xilinx Video IP Core
      4 *
      5 * Copyright (C) 2013-2015 Ideas on Board
      6 * Copyright (C) 2013-2015 Xilinx, Inc.
      7 *
      8 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
      9 *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
     10 */
     11
     12#include <linux/clk.h>
     13#include <linux/export.h>
     14#include <linux/kernel.h>
     15#include <linux/of.h>
     16#include <linux/platform_device.h>
     17
     18#include <dt-bindings/media/xilinx-vip.h>
     19
     20#include "xilinx-vip.h"
     21
     22/* -----------------------------------------------------------------------------
     23 * Helper functions
     24 */
     25
     26static const struct xvip_video_format xvip_video_formats[] = {
     27	{ XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
     28	  2, V4L2_PIX_FMT_YUYV },
     29	{ XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
     30	  3, V4L2_PIX_FMT_YUV444 },
     31	{ XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
     32	  3, 0 },
     33	{ XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8,
     34	  1, V4L2_PIX_FMT_GREY },
     35	{ XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8,
     36	  1, V4L2_PIX_FMT_SRGGB8 },
     37	{ XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8,
     38	  1, V4L2_PIX_FMT_SGRBG8 },
     39	{ XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8,
     40	  1, V4L2_PIX_FMT_SGBRG8 },
     41	{ XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8,
     42	  1, V4L2_PIX_FMT_SBGGR8 },
     43};
     44
     45/**
     46 * xvip_get_format_by_code - Retrieve format information for a media bus code
     47 * @code: the format media bus code
     48 *
     49 * Return: a pointer to the format information structure corresponding to the
     50 * given V4L2 media bus format @code, or ERR_PTR if no corresponding format can
     51 * be found.
     52 */
     53const struct xvip_video_format *xvip_get_format_by_code(unsigned int code)
     54{
     55	unsigned int i;
     56
     57	for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
     58		const struct xvip_video_format *format = &xvip_video_formats[i];
     59
     60		if (format->code == code)
     61			return format;
     62	}
     63
     64	return ERR_PTR(-EINVAL);
     65}
     66EXPORT_SYMBOL_GPL(xvip_get_format_by_code);
     67
     68/**
     69 * xvip_get_format_by_fourcc - Retrieve format information for a 4CC
     70 * @fourcc: the format 4CC
     71 *
     72 * Return: a pointer to the format information structure corresponding to the
     73 * given V4L2 format @fourcc. If not found, return a pointer to the first
     74 * available format (V4L2_PIX_FMT_YUYV).
     75 */
     76const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc)
     77{
     78	unsigned int i;
     79
     80	for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
     81		const struct xvip_video_format *format = &xvip_video_formats[i];
     82
     83		if (format->fourcc == fourcc)
     84			return format;
     85	}
     86
     87	return &xvip_video_formats[0];
     88}
     89EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc);
     90
     91/**
     92 * xvip_of_get_format - Parse a device tree node and return format information
     93 * @node: the device tree node
     94 *
     95 * Read the xlnx,video-format, xlnx,video-width and xlnx,cfa-pattern properties
     96 * from the device tree @node passed as an argument and return the corresponding
     97 * format information.
     98 *
     99 * Return: a pointer to the format information structure corresponding to the
    100 * format name and width, or ERR_PTR if no corresponding format can be found.
    101 */
    102const struct xvip_video_format *xvip_of_get_format(struct device_node *node)
    103{
    104	const char *pattern = "mono";
    105	unsigned int vf_code;
    106	unsigned int i;
    107	u32 width;
    108	int ret;
    109
    110	ret = of_property_read_u32(node, "xlnx,video-format", &vf_code);
    111	if (ret < 0)
    112		return ERR_PTR(ret);
    113
    114	ret = of_property_read_u32(node, "xlnx,video-width", &width);
    115	if (ret < 0)
    116		return ERR_PTR(ret);
    117
    118	if (vf_code == XVIP_VF_MONO_SENSOR)
    119		of_property_read_string(node, "xlnx,cfa-pattern", &pattern);
    120
    121	for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
    122		const struct xvip_video_format *format = &xvip_video_formats[i];
    123
    124		if (format->vf_code != vf_code || format->width != width)
    125			continue;
    126
    127		if (vf_code == XVIP_VF_MONO_SENSOR &&
    128		    strcmp(pattern, format->pattern))
    129			continue;
    130
    131		return format;
    132	}
    133
    134	return ERR_PTR(-EINVAL);
    135}
    136EXPORT_SYMBOL_GPL(xvip_of_get_format);
    137
    138/**
    139 * xvip_set_format_size - Set the media bus frame format size
    140 * @format: V4L2 frame format on media bus
    141 * @fmt: media bus format
    142 *
    143 * Set the media bus frame format size. The width / height from the subdevice
    144 * format are set to the given media bus format. The new format size is stored
    145 * in @format. The width and height are clamped using default min / max values.
    146 */
    147void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
    148			  const struct v4l2_subdev_format *fmt)
    149{
    150	format->width = clamp_t(unsigned int, fmt->format.width,
    151				XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
    152	format->height = clamp_t(unsigned int, fmt->format.height,
    153			 XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
    154}
    155EXPORT_SYMBOL_GPL(xvip_set_format_size);
    156
    157/**
    158 * xvip_clr_or_set - Clear or set the register with a bitmask
    159 * @xvip: Xilinx Video IP device
    160 * @addr: address of register
    161 * @mask: bitmask to be set or cleared
    162 * @set: boolean flag indicating whether to set or clear
    163 *
    164 * Clear or set the register at address @addr with a bitmask @mask depending on
    165 * the boolean flag @set. When the flag @set is true, the bitmask is set in
    166 * the register, otherwise the bitmask is cleared from the register
    167 * when the flag @set is false.
    168 *
    169 * Fox example, this function can be used to set a control with a boolean value
    170 * requested by users. If the caller knows whether to set or clear in the first
    171 * place, the caller should call xvip_clr() or xvip_set() directly instead of
    172 * using this function.
    173 */
    174void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set)
    175{
    176	u32 reg;
    177
    178	reg = xvip_read(xvip, addr);
    179	reg = set ? reg | mask : reg & ~mask;
    180	xvip_write(xvip, addr, reg);
    181}
    182EXPORT_SYMBOL_GPL(xvip_clr_or_set);
    183
    184/**
    185 * xvip_clr_and_set - Clear and set the register with a bitmask
    186 * @xvip: Xilinx Video IP device
    187 * @addr: address of register
    188 * @clr: bitmask to be cleared
    189 * @set: bitmask to be set
    190 *
    191 * Clear a bit(s) of mask @clr in the register at address @addr, then set
    192 * a bit(s) of mask @set in the register after.
    193 */
    194void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set)
    195{
    196	u32 reg;
    197
    198	reg = xvip_read(xvip, addr);
    199	reg &= ~clr;
    200	reg |= set;
    201	xvip_write(xvip, addr, reg);
    202}
    203EXPORT_SYMBOL_GPL(xvip_clr_and_set);
    204
    205int xvip_init_resources(struct xvip_device *xvip)
    206{
    207	struct platform_device *pdev = to_platform_device(xvip->dev);
    208
    209	xvip->iomem = devm_platform_ioremap_resource(pdev, 0);
    210	if (IS_ERR(xvip->iomem))
    211		return PTR_ERR(xvip->iomem);
    212
    213	xvip->clk = devm_clk_get(xvip->dev, NULL);
    214	if (IS_ERR(xvip->clk))
    215		return PTR_ERR(xvip->clk);
    216
    217	clk_prepare_enable(xvip->clk);
    218	return 0;
    219}
    220EXPORT_SYMBOL_GPL(xvip_init_resources);
    221
    222void xvip_cleanup_resources(struct xvip_device *xvip)
    223{
    224	clk_disable_unprepare(xvip->clk);
    225}
    226EXPORT_SYMBOL_GPL(xvip_cleanup_resources);
    227
    228/* -----------------------------------------------------------------------------
    229 * Subdev operations handlers
    230 */
    231
    232/**
    233 * xvip_enum_mbus_code - Enumerate the media format code
    234 * @subdev: V4L2 subdevice
    235 * @sd_state: V4L2 subdev state
    236 * @code: returning media bus code
    237 *
    238 * Enumerate the media bus code of the subdevice. Return the corresponding
    239 * pad format code. This function only works for subdevices with fixed format
    240 * on all pads. Subdevices with multiple format should have their own
    241 * function to enumerate mbus codes.
    242 *
    243 * Return: 0 if the media bus code is found, or -EINVAL if the format index
    244 * is not valid.
    245 */
    246int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
    247			struct v4l2_subdev_state *sd_state,
    248			struct v4l2_subdev_mbus_code_enum *code)
    249{
    250	struct v4l2_mbus_framefmt *format;
    251
    252	/* Enumerating frame sizes based on the active configuration isn't
    253	 * supported yet.
    254	 */
    255	if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE)
    256		return -EINVAL;
    257
    258	if (code->index)
    259		return -EINVAL;
    260
    261	format = v4l2_subdev_get_try_format(subdev, sd_state, code->pad);
    262
    263	code->code = format->code;
    264
    265	return 0;
    266}
    267EXPORT_SYMBOL_GPL(xvip_enum_mbus_code);
    268
    269/**
    270 * xvip_enum_frame_size - Enumerate the media bus frame size
    271 * @subdev: V4L2 subdevice
    272 * @sd_state: V4L2 subdev state
    273 * @fse: returning media bus frame size
    274 *
    275 * This function is a drop-in implementation of the subdev enum_frame_size pad
    276 * operation. It assumes that the subdevice has one sink pad and one source
    277 * pad, and that the format on the source pad is always identical to the
    278 * format on the sink pad. Entities with different requirements need to
    279 * implement their own enum_frame_size handlers.
    280 *
    281 * Return: 0 if the media bus frame size is found, or -EINVAL
    282 * if the index or the code is not valid.
    283 */
    284int xvip_enum_frame_size(struct v4l2_subdev *subdev,
    285			 struct v4l2_subdev_state *sd_state,
    286			 struct v4l2_subdev_frame_size_enum *fse)
    287{
    288	struct v4l2_mbus_framefmt *format;
    289
    290	/* Enumerating frame sizes based on the active configuration isn't
    291	 * supported yet.
    292	 */
    293	if (fse->which == V4L2_SUBDEV_FORMAT_ACTIVE)
    294		return -EINVAL;
    295
    296	format = v4l2_subdev_get_try_format(subdev, sd_state, fse->pad);
    297
    298	if (fse->index || fse->code != format->code)
    299		return -EINVAL;
    300
    301	if (fse->pad == XVIP_PAD_SINK) {
    302		fse->min_width = XVIP_MIN_WIDTH;
    303		fse->max_width = XVIP_MAX_WIDTH;
    304		fse->min_height = XVIP_MIN_HEIGHT;
    305		fse->max_height = XVIP_MAX_HEIGHT;
    306	} else {
    307		/* The size on the source pad is fixed and always identical to
    308		 * the size on the sink pad.
    309		 */
    310		fse->min_width = format->width;
    311		fse->max_width = format->width;
    312		fse->min_height = format->height;
    313		fse->max_height = format->height;
    314	}
    315
    316	return 0;
    317}
    318EXPORT_SYMBOL_GPL(xvip_enum_frame_size);