brintos

brintos / linux-shallow public Read only

0
0
Text · 84.9 KiB · 1d89138 Raw
2975 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * V4L2 driver for the JPEG encoder/decoder from i.MX8QXP/i.MX8QM application4 * processors.5 *6 * The multi-planar buffers API is used.7 *8 * Baseline and extended sequential jpeg decoding is supported.9 * Progressive jpeg decoding is not supported by the IP.10 * Supports encode and decode of various formats:11 *     YUV444, YUV422, YUV420, BGR, ABGR, Gray12 * YUV420 is the only multi-planar format supported.13 * Minimum resolution is 64 x 64, maximum 8192 x 8192.14 * To achieve 8192 x 8192, modify in defconfig: CONFIG_CMA_SIZE_MBYTES=32015 * The alignment requirements for the resolution depend on the format,16 * multiple of 16 resolutions should work for all formats.17 * Special workarounds are made in the driver to support NV12 1080p.18 * When decoding, the driver detects image resolution and pixel format19 * from the jpeg stream, by parsing the jpeg markers.20 *21 * The IP has 4 slots available for context switching, but only slot 022 * was fully tested to work. Context switching is not used by the driver.23 * Each driver instance (context) allocates a slot for itself, but this24 * is postponed until device_run, to allow unlimited opens.25 *26 * The driver submits jobs to the IP by setting up a descriptor for the27 * used slot, and then validating it. The encoder has an additional descriptor28 * for the configuration phase. The driver expects FRM_DONE interrupt from29 * IP to mark the job as finished.30 *31 * The decoder IP has some limitations regarding the component ID's,32 * but the driver works around this by replacing them in the jpeg stream.33 *34 * A module parameter is available for debug purpose (jpeg_tracing), to enable35 * it, enable dynamic debug for this module and:36 * echo 1 > /sys/module/mxc_jpeg_encdec/parameters/jpeg_tracing37 *38 * This is inspired by the drivers/media/platform/samsung/s5p-jpeg driver39 *40 * Copyright 2018-2019 NXP41 */42 43#include <linux/kernel.h>44#include <linux/module.h>45#include <linux/io.h>46#include <linux/clk.h>47#include <linux/of_platform.h>48#include <linux/platform_device.h>49#include <linux/slab.h>50#include <linux/irqreturn.h>51#include <linux/interrupt.h>52#include <linux/pm_runtime.h>53#include <linux/pm_domain.h>54#include <linux/string.h>55 56#include <media/v4l2-jpeg.h>57#include <media/v4l2-mem2mem.h>58#include <media/v4l2-ioctl.h>59#include <media/v4l2-common.h>60#include <media/v4l2-event.h>61#include <media/videobuf2-dma-contig.h>62 63#include "mxc-jpeg-hw.h"64#include "mxc-jpeg.h"65 66static const struct mxc_jpeg_fmt mxc_formats[] = {67	{68		.name		= "JPEG",69		.fourcc		= V4L2_PIX_FMT_JPEG,70		.subsampling	= -1,71		.nc		= -1,72		.mem_planes	= 1,73		.comp_planes	= 1,74		.flags		= MXC_JPEG_FMT_TYPE_ENC,75	},76	{77		.name		= "BGR", /*BGR packed format*/78		.fourcc		= V4L2_PIX_FMT_BGR24,79		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,80		.nc		= 3,81		.depth		= 24,82		.mem_planes	= 1,83		.comp_planes	= 1,84		.h_align	= 3,85		.v_align	= 3,86		.flags		= MXC_JPEG_FMT_TYPE_RAW,87		.precision	= 8,88		.is_rgb		= 1,89	},90	{91		.name		= "BGR 12bit", /*12-bit BGR packed format*/92		.fourcc		= V4L2_PIX_FMT_BGR48_12,93		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,94		.nc		= 3,95		.depth		= 36,96		.mem_planes	= 1,97		.comp_planes	= 1,98		.h_align	= 3,99		.v_align	= 3,100		.flags		= MXC_JPEG_FMT_TYPE_RAW,101		.precision	= 12,102		.is_rgb		= 1,103	},104	{105		.name		= "ABGR", /* ABGR packed format */106		.fourcc		= V4L2_PIX_FMT_ABGR32,107		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,108		.nc		= 4,109		.depth		= 32,110		.mem_planes	= 1,111		.comp_planes	= 1,112		.h_align	= 3,113		.v_align	= 3,114		.flags		= MXC_JPEG_FMT_TYPE_RAW,115		.precision	= 8,116		.is_rgb		= 1,117	},118	{119		.name		= "ABGR 12bit", /* 12-bit ABGR packed format */120		.fourcc		= V4L2_PIX_FMT_ABGR64_12,121		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,122		.nc		= 4,123		.depth		= 48,124		.mem_planes	= 1,125		.comp_planes	= 1,126		.h_align	= 3,127		.v_align	= 3,128		.flags		= MXC_JPEG_FMT_TYPE_RAW,129		.precision	= 12,130		.is_rgb		= 1,131	},132	{133		.name		= "YUV420", /* 1st plane = Y, 2nd plane = UV */134		.fourcc		= V4L2_PIX_FMT_NV12M,135		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,136		.nc		= 3,137		.depth		= 12, /* 6 bytes (4Y + UV) for 4 pixels */138		.mem_planes	= 2,139		.comp_planes	= 2, /* 1 plane Y, 1 plane UV interleaved */140		.h_align	= 4,141		.v_align	= 4,142		.flags		= MXC_JPEG_FMT_TYPE_RAW,143		.precision	= 8,144	},145	{146		.name		= "YUV420", /* 1st plane = Y, 2nd plane = UV */147		.fourcc		= V4L2_PIX_FMT_NV12,148		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,149		.nc		= 3,150		.depth		= 12, /* 6 bytes (4Y + UV) for 4 pixels */151		.mem_planes	= 1,152		.comp_planes	= 2, /* 1 plane Y, 1 plane UV interleaved */153		.h_align	= 4,154		.v_align	= 4,155		.flags		= MXC_JPEG_FMT_TYPE_RAW,156		.precision	= 8,157	},158	{159		.name		= "YUV420 12bit", /* 1st plane = Y, 2nd plane = UV */160		.fourcc		= V4L2_PIX_FMT_P012M,161		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,162		.nc		= 3,163		.depth		= 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */164		.mem_planes	= 2,165		.comp_planes	= 2, /* 1 plane Y, 1 plane UV interleaved */166		.h_align	= 4,167		.v_align	= 4,168		.flags		= MXC_JPEG_FMT_TYPE_RAW,169		.precision	= 12,170	},171	{172		.name		= "YUV420 12bit", /* 1st plane = Y, 2nd plane = UV */173		.fourcc		= V4L2_PIX_FMT_P012,174		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,175		.nc		= 3,176		.depth		= 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */177		.mem_planes	= 1,178		.comp_planes	= 2, /* 1 plane Y, 1 plane UV interleaved */179		.h_align	= 4,180		.v_align	= 4,181		.flags		= MXC_JPEG_FMT_TYPE_RAW,182		.precision	= 12,183	},184	{185		.name		= "YUV422", /* YUYV */186		.fourcc		= V4L2_PIX_FMT_YUYV,187		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,188		.nc		= 3,189		.depth		= 16,190		.mem_planes	= 1,191		.comp_planes	= 1,192		.h_align	= 4,193		.v_align	= 3,194		.flags		= MXC_JPEG_FMT_TYPE_RAW,195		.precision	= 8,196	},197	{198		.name		= "YUV422 12bit", /* YUYV */199		.fourcc		= V4L2_PIX_FMT_Y212,200		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,201		.nc		= 3,202		.depth		= 24,203		.mem_planes	= 1,204		.comp_planes	= 1,205		.h_align	= 4,206		.v_align	= 3,207		.flags		= MXC_JPEG_FMT_TYPE_RAW,208		.precision	= 12,209	},210	{211		.name		= "YUV444", /* YUVYUV */212		.fourcc		= V4L2_PIX_FMT_YUV24,213		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,214		.nc		= 3,215		.depth		= 24,216		.mem_planes	= 1,217		.comp_planes	= 1,218		.h_align	= 3,219		.v_align	= 3,220		.flags		= MXC_JPEG_FMT_TYPE_RAW,221		.precision	= 8,222	},223	{224		.name		= "YUV444 12bit", /* YUVYUV */225		.fourcc		= V4L2_PIX_FMT_YUV48_12,226		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,227		.nc		= 3,228		.depth		= 36,229		.mem_planes	= 1,230		.comp_planes	= 1,231		.h_align	= 3,232		.v_align	= 3,233		.flags		= MXC_JPEG_FMT_TYPE_RAW,234		.precision	= 12,235	},236	{237		.name		= "Gray", /* Gray (Y8/Y12) or Single Comp */238		.fourcc		= V4L2_PIX_FMT_GREY,239		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,240		.nc		= 1,241		.depth		= 8,242		.mem_planes	= 1,243		.comp_planes	= 1,244		.h_align	= 3,245		.v_align	= 3,246		.flags		= MXC_JPEG_FMT_TYPE_RAW,247		.precision	= 8,248	},249	{250		.name		= "Gray 12bit", /* Gray (Y8/Y12) or Single Comp */251		.fourcc		= V4L2_PIX_FMT_Y012,252		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,253		.nc		= 1,254		.depth		= 12,255		.mem_planes	= 1,256		.comp_planes	= 1,257		.h_align	= 3,258		.v_align	= 3,259		.flags		= MXC_JPEG_FMT_TYPE_RAW,260		.precision	= 12,261	},262};263 264#define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats)265 266static const int mxc_decode_mode = MXC_JPEG_DECODE;267static const int mxc_encode_mode = MXC_JPEG_ENCODE;268 269static const struct of_device_id mxc_jpeg_match[] = {270	{271		.compatible = "nxp,imx8qxp-jpgdec",272		.data       = &mxc_decode_mode,273	},274	{275		.compatible = "nxp,imx8qxp-jpgenc",276		.data       = &mxc_encode_mode,277	},278	{ },279};280 281/*282 * default configuration stream, 64x64 yuv422283 * split by JPEG marker, so it's easier to modify & use284 */285static const unsigned char jpeg_soi[] = {286	0xFF, 0xD8287};288 289static const unsigned char jpeg_app0[] = {290	0xFF, 0xE0,291	0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00,292	0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01,293	0x00, 0x00294};295 296static const unsigned char jpeg_app14[] = {297	0xFF, 0xEE,298	0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65,299	0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00300};301 302static const unsigned char jpeg_dqt[] = {303	0xFF, 0xDB,304	0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E,305	0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12,306	0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18,307	0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D,308	0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33,309	0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40,310	0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6D,311	0x51, 0x57, 0x5F, 0x62, 0x67, 0x68, 0x67,312	0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, 0x78,313	0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12,314	0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A,315	0x2F, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,316	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,317	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,318	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,319	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,320	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,321	0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,322	0x63, 0x63, 0x63, 0x63, 0x63, 0x63323};324 325static const unsigned char jpeg_dqt_extseq[] = {326	0xFF, 0xDB,327	0x01, 0x04,328	0x10,329	0x00, 0x80, 0x00, 0x58, 0x00, 0x60, 0x00, 0x70,330	0x00, 0x60, 0x00, 0x50, 0x00, 0x80, 0x00, 0x70,331	0x00, 0x68, 0x00, 0x70, 0x00, 0x90, 0x00, 0x88,332	0x00, 0x80, 0x00, 0x98, 0x00, 0xC0, 0x01, 0x40,333	0x00, 0xD0, 0x00, 0xC0, 0x00, 0xB0, 0x00, 0xB0,334	0x00, 0xC0, 0x01, 0x88, 0x01, 0x18, 0x01, 0x28,335	0x00, 0xE8, 0x01, 0x40, 0x01, 0xD0, 0x01, 0x98,336	0x01, 0xE8, 0x01, 0xE0, 0x01, 0xC8, 0x01, 0x98,337	0x01, 0xC0, 0x01, 0xB8, 0x02, 0x00, 0x02, 0x40,338	0x02, 0xE0, 0x02, 0x70, 0x02, 0x00, 0x02, 0x20,339	0x02, 0xB8, 0x02, 0x28, 0x01, 0xB8, 0x01, 0xC0,340	0x02, 0x80, 0x03, 0x68, 0x02, 0x88, 0x02, 0xB8,341	0x02, 0xF8, 0x03, 0x10, 0x03, 0x38, 0x03, 0x40,342	0x03, 0x38, 0x01, 0xF0, 0x02, 0x68, 0x03, 0x88,343	0x03, 0xC8, 0x03, 0x80, 0x03, 0x20, 0x03, 0xC0,344	0x02, 0xE0, 0x03, 0x28, 0x03, 0x38, 0x03, 0x18,345	0x11,346	0x00, 0x88, 0x00, 0x90, 0x00, 0x90, 0x00, 0xC0,347	0x00, 0xA8, 0x00, 0xC0, 0x01, 0x78, 0x00, 0xD0,348	0x00, 0xD0, 0x01, 0x78, 0x03, 0x18, 0x02, 0x10,349	0x01, 0xC0, 0x02, 0x10, 0x03, 0x18, 0x03, 0x18,350	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,351	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,352	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,353	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,354	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,355	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,356	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,357	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,358	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,359	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,360	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,361	0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18,362};363 364static const unsigned char jpeg_sof_maximal[] = {365	0xFF, 0xC0,366	0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,367	0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,368	0x03, 0x11, 0x01, 0x04, 0x11, 0x01369};370 371static const unsigned char jpeg_sof_extseq[] = {372	0xFF, 0xC1,373	0x00, 0x14, 0x08, 0x00, 0x40, 0x00, 0x40,374	0x04, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,375	0x03, 0x11, 0x01, 0x04, 0x11, 0x01376};377 378static const unsigned char jpeg_dht[] = {379	0xFF, 0xC4,380	0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01,381	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,382	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,383	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,384	0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,385	0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05,386	0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01,387	0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,388	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,389	0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91,390	0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15,391	0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72,392	0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19,393	0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,394	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,395	0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,396	0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,397	0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,398	0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76,399	0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85,400	0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,401	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,402	0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,403	0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,404	0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,405	0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,406	0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,407	0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,408	0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3,409	0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,410	0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01,411	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,412	0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,413	0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,414	0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,415	0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,416	0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,417	0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,418	0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,419	0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,420	0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52,421	0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16,422	0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18,423	0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,424	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43,425	0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,426	0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,427	0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,428	0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,429	0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,430	0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93,431	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,432	0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,433	0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,434	0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4,435	0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2,436	0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,437	0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,438	0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5,439	0xF6, 0xF7, 0xF8, 0xF9, 0xFA440};441 442static const unsigned char jpeg_dht_extseq[] = {443	0xFF, 0xC4,444	0x02, 0x2a, 0x00, 0x00, 0x01, 0x05, 0x01,445	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,446	0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,447	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,448	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,449	0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,450	0x04, 0x03, 0x05, 0x05, 0x02, 0x03, 0x02,451	0x00, 0x00, 0xbf, 0x01, 0x02, 0x03, 0x00,452	0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,453	0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71,454	0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,455	0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,456	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a,457	0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26,458	0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,459	0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,460	0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,461	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,462	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,463	0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,464	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,465	0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,466	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,467	0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2,468	0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,469	0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,470	0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,471	0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,472	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,473	0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,474	0xf7, 0xf8, 0xf9, 0xfa, 0x0b, 0x0c, 0x0d,475	0x0e, 0x1b, 0x1c, 0x1d, 0x1e, 0x2b, 0x2c,476	0x2d, 0x2e, 0x3b, 0x3c, 0x3d, 0x3e, 0x4b,477	0x4c, 0x4d, 0x4e, 0x5b, 0x5c, 0x5d, 0x5e,478	0x6b, 0x6c, 0x6d, 0x6e, 0x7b, 0x7c, 0x7d,479	0x7e, 0x8b, 0x8c, 0x8d, 0x8e, 0x9b, 0x9c,480	0x9d, 0x9e, 0xab, 0xac, 0xad, 0xae, 0xbb,481	0xbc, 0xbd, 0xbe, 0xcb, 0xcc, 0xcd, 0xce,482	0xdb, 0xdc, 0xdd, 0xde, 0xeb, 0xec, 0xed,483	0xee, 0xfb, 0xfc, 0xfd, 0xfe, 0x01, 0x00,484	0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,485	0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,486	0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,487	0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,488	0x0d, 0x0e, 0x0f, 0x11, 0x00, 0x02, 0x01,489	0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05,490	0x02, 0x03, 0x02, 0x00, 0x00, 0xbf, 0x01,491	0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,492	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,493	0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91,494	0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,495	0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72,496	0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,497	0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,498	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,499	0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,500	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,501	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67,502	0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,503	0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,504	0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,505	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,506	0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,507	0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,508	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4,509	0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,510	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,511	0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,512	0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,513	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,514	0x0b, 0x0c, 0x0d, 0x0e, 0x1b, 0x1c, 0x1d,515	0x1e, 0x2b, 0x2c, 0x2d, 0x2e, 0x3b, 0x3c,516	0x3d, 0x3e, 0x4b, 0x4c, 0x4d, 0x4e, 0x5b,517	0x5c, 0x5d, 0x5e, 0x6b, 0x6c, 0x6d, 0x6e,518	0x7b, 0x7c, 0x7d, 0x7e, 0x8b, 0x8c, 0x8d,519	0x8e, 0x9b, 0x9c, 0x9d, 0x9e, 0xab, 0xac,520	0xad, 0xae, 0xbb, 0xbc, 0xbd, 0xbe, 0xcb,521	0xcc, 0xcd, 0xce, 0xdb, 0xdc, 0xdd, 0xde,522	0xeb, 0xec, 0xed, 0xee, 0xfb, 0xfc, 0xfd,523	0xfe,524};525 526static const unsigned char jpeg_dri[] = {527	0xFF, 0xDD,528	0x00, 0x04, 0x00, 0x20529};530 531static const unsigned char jpeg_sos_maximal[] = {532	0xFF, 0xDA,533	0x00, 0x0C, 0x04, 0x01, 0x00, 0x02, 0x11, 0x03,534	0x11, 0x04, 0x11, 0x00, 0x3F, 0x00535};536 537static const unsigned char jpeg_image_red[] = {538	0xFC, 0x5F, 0xA2, 0xBF, 0xCA, 0x73, 0xFE, 0xFE,539	0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,540	0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,541	0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,542	0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,543	0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0,544	0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00,545	0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02,546	0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00, 0x28,547	0xA0, 0x02, 0x8A, 0x00, 0x28, 0xA0, 0x02, 0x8A,548	0x00, 0x28, 0xA0, 0x02, 0x8A, 0x00549};550 551static const unsigned char jpeg_eoi[] = {552	0xFF, 0xD9553};554 555struct mxc_jpeg_src_buf {556	/* common v4l buffer stuff -- must be first */557	struct vb2_v4l2_buffer	b;558	struct list_head	list;559 560	/* mxc-jpeg specific */561	bool			dht_needed;562	bool			jpeg_parse_error;563	const struct mxc_jpeg_fmt	*fmt;564	int			w;565	int			h;566};567 568static inline struct mxc_jpeg_src_buf *vb2_to_mxc_buf(struct vb2_buffer *vb)569{570	return container_of(to_vb2_v4l2_buffer(vb),571			    struct mxc_jpeg_src_buf, b);572}573 574static unsigned int debug;575module_param(debug, int, 0644);576MODULE_PARM_DESC(debug, "Debug level (0-3)");577 578static unsigned int hw_timeout = 2000;579module_param(hw_timeout, int, 0644);580MODULE_PARM_DESC(hw_timeout, "MXC JPEG hw timeout, the number of milliseconds");581 582static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision);583static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q);584 585static void _bswap16(u16 *a)586{587	*a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8);588}589 590static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf,591			  unsigned long len)592{593	unsigned int plane_no;594	u32 dma_addr;595	void *vaddr;596	unsigned long payload;597 598	if (debug < 3)599		return;600 601	for (plane_no = 0; plane_no < buf->num_planes; plane_no++) {602		payload = vb2_get_plane_payload(buf, plane_no);603		if (len == 0)604			len = payload;605		dma_addr = vb2_dma_contig_plane_dma_addr(buf, plane_no);606		vaddr = vb2_plane_vaddr(buf, plane_no);607		v4l2_dbg(3, debug, &jpeg->v4l2_dev,608			 "plane %d (vaddr=%p dma_addr=%x payload=%ld):",609			  plane_no, vaddr, dma_addr, payload);610		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,611			       vaddr, len, false);612	}613}614 615static inline struct mxc_jpeg_ctx *mxc_jpeg_fh_to_ctx(struct v4l2_fh *fh)616{617	return container_of(fh, struct mxc_jpeg_ctx, fh);618}619 620static int enum_fmt(const struct mxc_jpeg_fmt *mxc_formats, int n,621		    struct v4l2_fmtdesc *f, u32 type)622{623	int i, num = 0;624 625	for (i = 0; i < n; ++i) {626		if (mxc_formats[i].flags == type) {627			/* index-th format of searched type found ? */628			if (num == f->index)629				break;630			/* Correct type but haven't reached our index yet,631			 * just increment per-type index632			 */633			++num;634		}635	}636 637	/* Format not found */638	if (i >= n)639		return -EINVAL;640 641	f->pixelformat = mxc_formats[i].fourcc;642 643	return 0;644}645 646static const struct mxc_jpeg_fmt *mxc_jpeg_find_format(u32 pixelformat)647{648	unsigned int k;649 650	for (k = 0; k < MXC_JPEG_NUM_FORMATS; k++) {651		const struct mxc_jpeg_fmt *fmt = &mxc_formats[k];652 653		if (fmt->fourcc == pixelformat)654			return fmt;655	}656	return NULL;657}658 659static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)660{661	switch (fourcc) {662	case V4L2_PIX_FMT_GREY:663	case V4L2_PIX_FMT_Y012:664		return MXC_JPEG_GRAY;665	case V4L2_PIX_FMT_YUYV:666	case V4L2_PIX_FMT_Y212:667		return MXC_JPEG_YUV422;668	case V4L2_PIX_FMT_NV12:669	case V4L2_PIX_FMT_NV12M:670	case V4L2_PIX_FMT_P012:671	case V4L2_PIX_FMT_P012M:672		return MXC_JPEG_YUV420;673	case V4L2_PIX_FMT_YUV24:674	case V4L2_PIX_FMT_YUV48_12:675		return MXC_JPEG_YUV444;676	case V4L2_PIX_FMT_BGR24:677	case V4L2_PIX_FMT_BGR48_12:678		return MXC_JPEG_BGR;679	case V4L2_PIX_FMT_ABGR32:680	case V4L2_PIX_FMT_ABGR64_12:681		return MXC_JPEG_ABGR;682	default:683		return MXC_JPEG_INVALID;684	}685}686 687static struct mxc_jpeg_q_data *mxc_jpeg_get_q_data(struct mxc_jpeg_ctx *ctx,688						   enum v4l2_buf_type type)689{690	if (V4L2_TYPE_IS_OUTPUT(type))691		return &ctx->out_q;692	return &ctx->cap_q;693}694 695static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,696			   struct vb2_buffer *raw_buf,697			   struct vb2_buffer *jpeg_buf, int offset)698{699	int img_fmt = desc->stm_ctrl & STM_CTRL_IMAGE_FORMAT_MASK;700	struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(raw_buf->vb2_queue);701	struct mxc_jpeg_q_data *q_data;702 703	q_data = mxc_jpeg_get_q_data(ctx, raw_buf->type);704	desc->buf_base0 = vb2_dma_contig_plane_dma_addr(raw_buf, 0);705	desc->buf_base1 = 0;706	if (img_fmt == STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV420)) {707		if (raw_buf->num_planes == 2)708			desc->buf_base1 = vb2_dma_contig_plane_dma_addr(raw_buf, 1);709		else710			desc->buf_base1 = desc->buf_base0 + q_data->sizeimage[0];711	}712	desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(jpeg_buf, 0) +713		offset;714}715 716static bool mxc_jpeg_is_extended_sequential(const struct mxc_jpeg_fmt *fmt)717{718	if (!fmt || !(fmt->flags & MXC_JPEG_FMT_TYPE_RAW))719		return false;720 721	if (fmt->precision > 8)722		return true;723 724	return false;725}726 727static void notify_eos(struct mxc_jpeg_ctx *ctx)728{729	const struct v4l2_event ev = {730		.type = V4L2_EVENT_EOS731	};732 733	dev_dbg(ctx->mxc_jpeg->dev, "Notify app event EOS reached");734	v4l2_event_queue_fh(&ctx->fh, &ev);735}736 737static void notify_src_chg(struct mxc_jpeg_ctx *ctx)738{739	const struct v4l2_event ev = {740		.type = V4L2_EVENT_SOURCE_CHANGE,741		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,742	};743 744	dev_dbg(ctx->mxc_jpeg->dev, "Notify app event SRC_CH_RESOLUTION");745	v4l2_event_queue_fh(&ctx->fh, &ev);746}747 748static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)749{750	if (!slot_data->used)751		return slot_data->slot;752	return -1;753}754 755static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)756{757	struct mxc_jpeg_desc *desc;758	struct mxc_jpeg_desc *cfg_desc;759	void *cfg_stm;760 761	if (jpeg->slot_data.desc)762		goto skip_alloc; /* already allocated, reuse it */763 764	/* allocate descriptor for decoding/encoding phase */765	desc = dma_alloc_coherent(jpeg->dev,766				  sizeof(struct mxc_jpeg_desc),767				  &jpeg->slot_data.desc_handle,768				  GFP_ATOMIC);769	if (!desc)770		goto err;771	jpeg->slot_data.desc = desc;772 773	/* allocate descriptor for configuration phase (encoder only) */774	cfg_desc = dma_alloc_coherent(jpeg->dev,775				      sizeof(struct mxc_jpeg_desc),776				      &jpeg->slot_data.cfg_desc_handle,777				      GFP_ATOMIC);778	if (!cfg_desc)779		goto err;780	jpeg->slot_data.cfg_desc = cfg_desc;781 782	/* allocate configuration stream */783	cfg_stm = dma_alloc_coherent(jpeg->dev,784				     MXC_JPEG_MAX_CFG_STREAM,785				     &jpeg->slot_data.cfg_stream_handle,786				     GFP_ATOMIC);787	if (!cfg_stm)788		goto err;789	jpeg->slot_data.cfg_stream_vaddr = cfg_stm;790 791skip_alloc:792	jpeg->slot_data.used = true;793 794	return true;795err:796	dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot);797 798	return false;799}800 801static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)802{803	/* free descriptor for decoding/encoding phase */804	dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),805			  jpeg->slot_data.desc,806			  jpeg->slot_data.desc_handle);807 808	/* free descriptor for encoder configuration phase / decoder DHT */809	dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),810			  jpeg->slot_data.cfg_desc,811			  jpeg->slot_data.cfg_desc_handle);812 813	/* free configuration stream */814	dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,815			  jpeg->slot_data.cfg_stream_vaddr,816			  jpeg->slot_data.cfg_stream_handle);817 818	jpeg->slot_data.used = false;819}820 821static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx,822					       struct vb2_v4l2_buffer *src_buf,823					       struct vb2_v4l2_buffer *dst_buf)824{825	if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {826		dst_buf->flags |= V4L2_BUF_FLAG_LAST;827		v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);828		notify_eos(ctx);829		ctx->header_parsed = false;830	}831}832 833static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state state, bool reset)834{835	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;836	void __iomem *reg = jpeg->base_reg;837	struct vb2_v4l2_buffer *src_buf, *dst_buf;838 839	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);840	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);841	mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf);842	v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);843	v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);844	v4l2_m2m_buf_done(src_buf, state);845	v4l2_m2m_buf_done(dst_buf, state);846 847	mxc_jpeg_disable_irq(reg, ctx->slot);848	jpeg->slot_data.used = false;849	if (reset)850		mxc_jpeg_sw_reset(reg);851}852 853static u32 mxc_jpeg_get_plane_size(struct mxc_jpeg_q_data *q_data, u32 plane_no)854{855	const struct mxc_jpeg_fmt *fmt = q_data->fmt;856	u32 size;857	int i;858 859	if (plane_no >= fmt->mem_planes)860		return 0;861 862	if (fmt->mem_planes == fmt->comp_planes)863		return q_data->sizeimage[plane_no];864 865	if (plane_no < fmt->mem_planes - 1)866		return q_data->sizeimage[plane_no];867 868	size = q_data->sizeimage[fmt->mem_planes - 1];869 870	/* Should be impossible given mxc_formats. */871	if (WARN_ON_ONCE(fmt->comp_planes > ARRAY_SIZE(q_data->sizeimage)))872		return size;873 874	for (i = fmt->mem_planes; i < fmt->comp_planes; i++)875		size += q_data->sizeimage[i];876 877	return size;878}879 880static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)881{882	struct mxc_jpeg_dev *jpeg = priv;883	struct mxc_jpeg_ctx *ctx;884	void __iomem *reg = jpeg->base_reg;885	struct device *dev = jpeg->dev;886	struct vb2_v4l2_buffer *src_buf, *dst_buf;887	struct mxc_jpeg_src_buf *jpeg_src_buf;888	enum vb2_buffer_state buf_state;889	u32 dec_ret, com_status;890	unsigned long payload;891	struct mxc_jpeg_q_data *q_data;892	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;893	unsigned int slot;894 895	spin_lock(&jpeg->hw_lock);896 897	com_status = readl(reg + COM_STATUS);898	slot = COM_STATUS_CUR_SLOT(com_status);899	dev_dbg(dev, "Irq %d on slot %d.\n", irq, slot);900 901	ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);902	if (WARN_ON(!ctx))903		goto job_unlock;904 905	if (slot != ctx->slot) {906		/* TODO investigate when adding multi-instance support */907		dev_warn(dev, "IRQ slot %d != context slot %d.\n",908			 slot, ctx->slot);909		goto job_unlock;910	}911 912	if (!jpeg->slot_data.used)913		goto job_unlock;914 915	dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));916	writel(dec_ret, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); /* w1c */917 918	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);919	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);920	if (!dst_buf || !src_buf) {921		dev_err(dev, "No source or destination buffer.\n");922		goto job_unlock;923	}924	jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);925 926	if (dec_ret & SLOT_STATUS_ENC_CONFIG_ERR) {927		u32 ret = readl(reg + CAST_STATUS12);928 929		dev_err(dev, "Encoder/decoder error, dec_ret = 0x%08x, status=0x%08x",930			dec_ret, ret);931		mxc_jpeg_clr_desc(reg, slot);932		mxc_jpeg_sw_reset(reg);933		buf_state = VB2_BUF_STATE_ERROR;934		goto buffers_done;935	}936 937	if (!(dec_ret & SLOT_STATUS_FRMDONE))938		goto job_unlock;939 940	if (jpeg->mode == MXC_JPEG_ENCODE &&941	    ctx->enc_state == MXC_JPEG_ENC_CONF) {942		q_data = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);943		ctx->enc_state = MXC_JPEG_ENCODING;944		dev_dbg(dev, "Encoder config finished. Start encoding...\n");945		mxc_jpeg_enc_set_quality(dev, reg, ctx->jpeg_quality);946		mxc_jpeg_enc_mode_go(dev, reg, mxc_jpeg_is_extended_sequential(q_data->fmt));947		goto job_unlock;948	}949	if (jpeg->mode == MXC_JPEG_DECODE && jpeg_src_buf->dht_needed) {950		jpeg_src_buf->dht_needed = false;951		dev_dbg(dev, "Decoder DHT cfg finished. Start decoding...\n");952		goto job_unlock;953	}954 955	if (jpeg->mode == MXC_JPEG_ENCODE) {956		payload = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_BUF_PTR));957		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);958		dev_dbg(dev, "Encoding finished, payload size: %ld\n",959			payload);960	} else {961		q_data = mxc_jpeg_get_q_data(ctx, cap_type);962		payload = mxc_jpeg_get_plane_size(q_data, 0);963		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload);964		vb2_set_plane_payload(&dst_buf->vb2_buf, 1, 0);965		if (q_data->fmt->mem_planes == 2) {966			payload = mxc_jpeg_get_plane_size(q_data, 1);967			vb2_set_plane_payload(&dst_buf->vb2_buf, 1, payload);968		}969		dev_dbg(dev, "Decoding finished, payload size: %ld + %ld\n",970			vb2_get_plane_payload(&dst_buf->vb2_buf, 0),971			vb2_get_plane_payload(&dst_buf->vb2_buf, 1));972	}973 974	/* short preview of the results */975	dev_dbg(dev, "src_buf preview: ");976	print_mxc_buf(jpeg, &src_buf->vb2_buf, 32);977	dev_dbg(dev, "dst_buf preview: ");978	print_mxc_buf(jpeg, &dst_buf->vb2_buf, 32);979	buf_state = VB2_BUF_STATE_DONE;980 981buffers_done:982	mxc_jpeg_job_finish(ctx, buf_state, false);983	spin_unlock(&jpeg->hw_lock);984	cancel_delayed_work(&ctx->task_timer);985	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);986	return IRQ_HANDLED;987job_unlock:988	spin_unlock(&jpeg->hw_lock);989	return IRQ_HANDLED;990}991 992static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,993			      u32 fourcc,994			      u16 w, u16 h)995{996	int sof_length;997	const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(fourcc);998 999	if (fmt)1000		sof->precision = fmt->precision;1001	else1002		sof->precision = 8; /* TODO allow 8/12 bit precision*/1003	sof->height = h;1004	_bswap16(&sof->height);1005	sof->width = w;1006	_bswap16(&sof->width);1007 1008	switch (fourcc) {1009	case V4L2_PIX_FMT_NV12:1010	case V4L2_PIX_FMT_NV12M:1011	case V4L2_PIX_FMT_P012:1012	case V4L2_PIX_FMT_P012M:1013		sof->components_no = 3;1014		sof->comp[0].v = 0x2;1015		sof->comp[0].h = 0x2;1016		break;1017	case V4L2_PIX_FMT_YUYV:1018	case V4L2_PIX_FMT_Y212:1019		sof->components_no = 3;1020		sof->comp[0].v = 0x1;1021		sof->comp[0].h = 0x2;1022		break;1023	case V4L2_PIX_FMT_YUV24:1024	case V4L2_PIX_FMT_YUV48_12:1025	case V4L2_PIX_FMT_BGR24:1026	case V4L2_PIX_FMT_BGR48_12:1027	default:1028		sof->components_no = 3;1029		break;1030	case V4L2_PIX_FMT_ABGR32:1031	case V4L2_PIX_FMT_ABGR64_12:1032		sof->components_no = 4;1033		break;1034	case V4L2_PIX_FMT_GREY:1035	case V4L2_PIX_FMT_Y012:1036		sof->components_no = 1;1037		break;1038	}1039	sof_length = 8 + 3 * sof->components_no;1040	sof->length = sof_length;1041	_bswap16(&sof->length);1042 1043	return sof_length; /* not swaped */1044}1045 1046static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,1047			      u32 fourcc)1048{1049	int sos_length;1050	u8 *sof_u8 = (u8 *)sos;1051 1052	switch (fourcc) {1053	case V4L2_PIX_FMT_NV12:1054	case V4L2_PIX_FMT_NV12M:1055	case V4L2_PIX_FMT_P012:1056	case V4L2_PIX_FMT_P012M:1057		sos->components_no = 3;1058		break;1059	case V4L2_PIX_FMT_YUYV:1060	case V4L2_PIX_FMT_Y212:1061		sos->components_no = 3;1062		break;1063	case V4L2_PIX_FMT_YUV24:1064	case V4L2_PIX_FMT_YUV48_12:1065	case V4L2_PIX_FMT_BGR24:1066	case V4L2_PIX_FMT_BGR48_12:1067	default:1068		sos->components_no = 3;1069		break;1070	case V4L2_PIX_FMT_ABGR32:1071	case V4L2_PIX_FMT_ABGR64_12:1072		sos->components_no = 4;1073		break;1074	case V4L2_PIX_FMT_GREY:1075	case V4L2_PIX_FMT_Y012:1076		sos->components_no = 1;1077		break;1078	}1079	sos_length = 6 + 2 * sos->components_no;1080	sos->length = sos_length;1081	_bswap16(&sos->length);1082 1083	/* SOS ignorable bytes, not so ignorable after all */1084	sof_u8[sos_length - 1] = 0x0;1085	sof_u8[sos_length - 2] = 0x3f;1086	sof_u8[sos_length - 3] = 0x0;1087 1088	return sos_length; /* not swaped */1089}1090 1091static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,1092					      u32 fourcc,1093					      u16 w, u16 h)1094{1095	/*1096	 * There is a hardware issue that first 128 bytes of configuration data1097	 * can't be loaded correctly.1098	 * To avoid this issue, we need to write the configuration from1099	 * an offset which should be no less than 0x80 (128 bytes).1100	 */1101	unsigned int offset = 0x80;1102	u8 *cfg = (u8 *)cfg_stream_vaddr;1103	struct mxc_jpeg_sof *sof;1104	struct mxc_jpeg_sos *sos;1105	const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(fourcc);1106 1107	if (!fmt)1108		return 0;1109 1110	memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi));1111	offset += ARRAY_SIZE(jpeg_soi);1112 1113	if (fmt->is_rgb) {1114		memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14));1115		offset += sizeof(jpeg_app14);1116	} else {1117		memcpy(cfg + offset, jpeg_app0, sizeof(jpeg_app0));1118		offset += sizeof(jpeg_app0);1119	}1120 1121	if (mxc_jpeg_is_extended_sequential(fmt)) {1122		memcpy(cfg + offset, jpeg_dqt_extseq, sizeof(jpeg_dqt_extseq));1123		offset += sizeof(jpeg_dqt_extseq);1124 1125		memcpy(cfg + offset, jpeg_sof_extseq, sizeof(jpeg_sof_extseq));1126	} else {1127		memcpy(cfg + offset, jpeg_dqt, sizeof(jpeg_dqt));1128		offset += sizeof(jpeg_dqt);1129 1130		memcpy(cfg + offset, jpeg_sof_maximal, sizeof(jpeg_sof_maximal));1131	}1132	offset += 2; /* skip marker ID */1133	sof = (struct mxc_jpeg_sof *)(cfg + offset);1134	offset += mxc_jpeg_fixup_sof(sof, fourcc, w, h);1135 1136	if (mxc_jpeg_is_extended_sequential(fmt)) {1137		memcpy(cfg + offset, jpeg_dht_extseq, sizeof(jpeg_dht_extseq));1138		offset += sizeof(jpeg_dht_extseq);1139	} else {1140		memcpy(cfg + offset, jpeg_dht, sizeof(jpeg_dht));1141		offset += sizeof(jpeg_dht);1142	}1143 1144	memcpy(cfg + offset, jpeg_dri, sizeof(jpeg_dri));1145	offset += sizeof(jpeg_dri);1146 1147	memcpy(cfg + offset, jpeg_sos_maximal, sizeof(jpeg_sos_maximal));1148	offset += 2; /* skip marker ID */1149	sos = (struct mxc_jpeg_sos *)(cfg + offset);1150	offset += mxc_jpeg_fixup_sos(sos, fourcc);1151 1152	memcpy(cfg + offset, jpeg_image_red, sizeof(jpeg_image_red));1153	offset += sizeof(jpeg_image_red);1154 1155	memcpy(cfg + offset, jpeg_eoi, sizeof(jpeg_eoi));1156	offset += sizeof(jpeg_eoi);1157 1158	return offset;1159}1160 1161static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,1162				     struct mxc_jpeg_ctx *ctx,1163				     struct vb2_buffer *src_buf,1164				     struct vb2_buffer *dst_buf)1165{1166	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;1167	struct mxc_jpeg_q_data *q_data_cap;1168	enum mxc_jpeg_image_format img_fmt;1169	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;1170	void __iomem *reg = jpeg->base_reg;1171	unsigned int slot = ctx->slot;1172	struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;1173	struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;1174	dma_addr_t desc_handle = jpeg->slot_data.desc_handle;1175	dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;1176	dma_addr_t cfg_stream_handle = jpeg->slot_data.cfg_stream_handle;1177	unsigned int *cfg_size = &jpeg->slot_data.cfg_stream_size;1178	void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;1179	struct mxc_jpeg_src_buf *jpeg_src_buf;1180 1181	jpeg_src_buf = vb2_to_mxc_buf(src_buf);1182 1183	/* setup the decoding descriptor */1184	desc->next_descpt_ptr = 0; /* end of chain */1185	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);1186	desc->imgsize = q_data_cap->w_adjusted << 16 | q_data_cap->h_adjusted;1187	img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data_cap->fmt->fourcc);1188	desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */1189	desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);1190	desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);1191	if (mxc_jpeg_is_extended_sequential(jpeg_src_buf->fmt))1192		desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION;1193	else1194		desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION;1195	desc->line_pitch = q_data_cap->bytesperline[0];1196	mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);1197	mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024));1198	print_descriptor_info(jpeg->dev, desc);1199 1200	if (!jpeg_src_buf->dht_needed) {1201		/* validate the decoding descriptor */1202		mxc_jpeg_set_desc(desc_handle, reg, slot);1203		return;1204	}1205 1206	/*1207	 * if a default huffman table is needed, use the config descriptor to1208	 * inject a DHT, by chaining it before the decoding descriptor1209	 */1210	*cfg_size = mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,1211					      V4L2_PIX_FMT_YUYV,1212					      MXC_JPEG_MIN_WIDTH,1213					      MXC_JPEG_MIN_HEIGHT);1214	cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;1215	cfg_desc->buf_base0 = vb2_dma_contig_plane_dma_addr(dst_buf, 0);1216	cfg_desc->buf_base1 = 0;1217	cfg_desc->imgsize = MXC_JPEG_MIN_WIDTH << 16;1218	cfg_desc->imgsize |= MXC_JPEG_MIN_HEIGHT;1219	cfg_desc->line_pitch = MXC_JPEG_MIN_WIDTH * 2;1220	cfg_desc->stm_ctrl = STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV422);1221	cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);1222	cfg_desc->stm_bufbase = cfg_stream_handle;1223	cfg_desc->stm_bufsize = ALIGN(*cfg_size, 1024);1224	print_descriptor_info(jpeg->dev, cfg_desc);1225 1226	/* validate the configuration descriptor */1227	mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);1228}1229 1230static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,1231				     struct mxc_jpeg_ctx *ctx,1232				     struct vb2_buffer *src_buf,1233				     struct vb2_buffer *dst_buf)1234{1235	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;1236	void __iomem *reg = jpeg->base_reg;1237	unsigned int slot = ctx->slot;1238	struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;1239	struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;1240	dma_addr_t desc_handle = jpeg->slot_data.desc_handle;1241	dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;1242	void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;1243	struct mxc_jpeg_q_data *q_data;1244	enum mxc_jpeg_image_format img_fmt;1245	int w, h;1246 1247	q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);1248 1249	jpeg->slot_data.cfg_stream_size =1250			mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,1251						  q_data->fmt->fourcc,1252						  q_data->crop.width,1253						  q_data->crop.height);1254 1255	/* chain the config descriptor with the encoding descriptor */1256	cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;1257 1258	cfg_desc->buf_base0 = jpeg->slot_data.cfg_stream_handle;1259	cfg_desc->buf_base1 = 0;1260	cfg_desc->line_pitch = 0;1261	cfg_desc->stm_bufbase = 0; /* no output expected */1262	cfg_desc->stm_bufsize = 0x0;1263	cfg_desc->imgsize = 0;1264	cfg_desc->stm_ctrl = STM_CTRL_CONFIG_MOD(1);1265	cfg_desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);1266 1267	desc->next_descpt_ptr = 0; /* end of chain */1268 1269	/* use adjusted resolution for CAST IP job */1270	w = q_data->crop.width;1271	h = q_data->crop.height;1272	v4l_bound_align_image(&w, w, MXC_JPEG_MAX_WIDTH, q_data->fmt->h_align,1273			      &h, h, MXC_JPEG_MAX_HEIGHT, q_data->fmt->v_align, 0);1274	mxc_jpeg_set_res(desc, w, h);1275	mxc_jpeg_set_line_pitch(desc, q_data->bytesperline[0]);1276	mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(dst_buf, 0), 1024));1277	img_fmt = mxc_jpeg_fourcc_to_imgfmt(q_data->fmt->fourcc);1278	if (img_fmt == MXC_JPEG_INVALID)1279		dev_err(jpeg->dev, "No valid image format detected\n");1280	desc->stm_ctrl = STM_CTRL_CONFIG_MOD(0) |1281			 STM_CTRL_IMAGE_FORMAT(img_fmt);1282	desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);1283	if (mxc_jpeg_is_extended_sequential(q_data->fmt))1284		desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION;1285	else1286		desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION;1287	mxc_jpeg_addrs(desc, src_buf, dst_buf, 0);1288	dev_dbg(jpeg->dev, "cfg_desc:\n");1289	print_descriptor_info(jpeg->dev, cfg_desc);1290	dev_dbg(jpeg->dev, "enc desc:\n");1291	print_descriptor_info(jpeg->dev, desc);1292	print_wrapper_info(jpeg->dev, reg);1293	print_cast_status(jpeg->dev, reg, MXC_JPEG_ENCODE);1294 1295	/* validate the configuration descriptor */1296	mxc_jpeg_set_desc(cfg_desc_handle, reg, slot);1297}1298 1299static const struct mxc_jpeg_fmt *mxc_jpeg_get_sibling_format(const struct mxc_jpeg_fmt *fmt)1300{1301	int i;1302 1303	for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++) {1304		if (mxc_formats[i].subsampling == fmt->subsampling &&1305		    mxc_formats[i].nc == fmt->nc &&1306		    mxc_formats[i].precision == fmt->precision &&1307		    mxc_formats[i].is_rgb == fmt->is_rgb &&1308		    mxc_formats[i].fourcc != fmt->fourcc)1309			return &mxc_formats[i];1310	}1311 1312	return NULL;1313}1314 1315static bool mxc_jpeg_compare_format(const struct mxc_jpeg_fmt *fmt1,1316				    const struct mxc_jpeg_fmt *fmt2)1317{1318	if (fmt1 == fmt2)1319		return true;1320	if (mxc_jpeg_get_sibling_format(fmt1) == fmt2)1321		return true;1322	return false;1323}1324 1325static void mxc_jpeg_set_last_buffer(struct mxc_jpeg_ctx *ctx)1326{1327	struct vb2_v4l2_buffer *next_dst_buf;1328 1329	next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);1330	if (!next_dst_buf) {1331		ctx->fh.m2m_ctx->is_draining = true;1332		ctx->fh.m2m_ctx->next_buf_last = true;1333		return;1334	}1335 1336	v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, next_dst_buf);1337}1338 1339static bool mxc_jpeg_source_change(struct mxc_jpeg_ctx *ctx,1340				   struct mxc_jpeg_src_buf *jpeg_src_buf)1341{1342	struct device *dev = ctx->mxc_jpeg->dev;1343	struct mxc_jpeg_q_data *q_data_cap;1344 1345	if (!jpeg_src_buf->fmt)1346		return false;1347 1348	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);1349	if (mxc_jpeg_compare_format(q_data_cap->fmt, jpeg_src_buf->fmt))1350		jpeg_src_buf->fmt = q_data_cap->fmt;1351	if (ctx->need_initial_source_change_evt ||1352	    q_data_cap->fmt != jpeg_src_buf->fmt ||1353	    q_data_cap->w != jpeg_src_buf->w ||1354	    q_data_cap->h != jpeg_src_buf->h) {1355		dev_dbg(dev, "Detected jpeg res=(%dx%d)->(%dx%d), pixfmt=%c%c%c%c\n",1356			q_data_cap->w, q_data_cap->h,1357			jpeg_src_buf->w, jpeg_src_buf->h,1358			(jpeg_src_buf->fmt->fourcc & 0xff),1359			(jpeg_src_buf->fmt->fourcc >>  8) & 0xff,1360			(jpeg_src_buf->fmt->fourcc >> 16) & 0xff,1361			(jpeg_src_buf->fmt->fourcc >> 24) & 0xff);1362 1363		/*1364		 * set-up the capture queue with the pixelformat and resolution1365		 * detected from the jpeg output stream1366		 */1367		q_data_cap->w = jpeg_src_buf->w;1368		q_data_cap->h = jpeg_src_buf->h;1369		q_data_cap->fmt = jpeg_src_buf->fmt;1370		q_data_cap->w_adjusted = q_data_cap->w;1371		q_data_cap->h_adjusted = q_data_cap->h;1372		q_data_cap->crop.left = 0;1373		q_data_cap->crop.top = 0;1374		q_data_cap->crop.width = jpeg_src_buf->w;1375		q_data_cap->crop.height = jpeg_src_buf->h;1376		q_data_cap->bytesperline[0] = 0;1377		q_data_cap->bytesperline[1] = 0;1378 1379		/*1380		 * align up the resolution for CAST IP,1381		 * but leave the buffer resolution unchanged1382		 */1383		v4l_bound_align_image(&q_data_cap->w_adjusted,1384				      q_data_cap->w_adjusted,  /* adjust up */1385				      MXC_JPEG_MAX_WIDTH,1386				      q_data_cap->fmt->h_align,1387				      &q_data_cap->h_adjusted,1388				      q_data_cap->h_adjusted, /* adjust up */1389				      MXC_JPEG_MAX_HEIGHT,1390				      q_data_cap->fmt->v_align,1391				      0);1392 1393		/* setup bytesperline/sizeimage for capture queue */1394		mxc_jpeg_bytesperline(q_data_cap, jpeg_src_buf->fmt->precision);1395		mxc_jpeg_sizeimage(q_data_cap);1396		notify_src_chg(ctx);1397		ctx->source_change = 1;1398		ctx->need_initial_source_change_evt = false;1399		if (vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))1400			mxc_jpeg_set_last_buffer(ctx);1401	}1402 1403	return ctx->source_change ? true : false;1404}1405 1406static int mxc_jpeg_job_ready(void *priv)1407{1408	struct mxc_jpeg_ctx *ctx = priv;1409 1410	return ctx->source_change ? 0 : 1;1411}1412 1413static void mxc_jpeg_device_run_timeout(struct work_struct *work)1414{1415	struct delayed_work *dwork = to_delayed_work(work);1416	struct mxc_jpeg_ctx *ctx = container_of(dwork, struct mxc_jpeg_ctx, task_timer);1417	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;1418	unsigned long flags;1419 1420	spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);1421	if (ctx->mxc_jpeg->slot_data.used) {1422		dev_warn(jpeg->dev, "%s timeout, cancel it\n",1423			 ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? "decode" : "encode");1424		mxc_jpeg_job_finish(ctx, VB2_BUF_STATE_ERROR, true);1425		v4l2_m2m_job_finish(ctx->mxc_jpeg->m2m_dev, ctx->fh.m2m_ctx);1426	}1427	spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);1428}1429 1430static void mxc_jpeg_device_run(void *priv)1431{1432	struct mxc_jpeg_ctx *ctx = priv;1433	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;1434	void __iomem *reg = jpeg->base_reg;1435	struct device *dev = jpeg->dev;1436	struct vb2_v4l2_buffer *src_buf, *dst_buf;1437	unsigned long flags;1438	struct mxc_jpeg_q_data *q_data_cap, *q_data_out;1439	struct mxc_jpeg_src_buf *jpeg_src_buf;1440 1441	spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);1442	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);1443	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);1444	if (!src_buf || !dst_buf) {1445		dev_err(dev, "Null src or dst buf\n");1446		goto end;1447	}1448 1449	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);1450	if (!q_data_cap)1451		goto end;1452	q_data_out = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);1453	if (!q_data_out)1454		goto end;1455	src_buf->sequence = q_data_out->sequence++;1456	dst_buf->sequence = q_data_cap->sequence++;1457 1458	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true);1459 1460	jpeg_src_buf = vb2_to_mxc_buf(&src_buf->vb2_buf);1461	if (q_data_cap->fmt->mem_planes != dst_buf->vb2_buf.num_planes) {1462		dev_err(dev, "Capture format %s has %d planes, but capture buffer has %d planes\n",1463			q_data_cap->fmt->name, q_data_cap->fmt->mem_planes,1464			dst_buf->vb2_buf.num_planes);1465		jpeg_src_buf->jpeg_parse_error = true;1466	}1467	if (jpeg_src_buf->jpeg_parse_error) {1468		mxc_jpeg_check_and_set_last_buffer(ctx, src_buf, dst_buf);1469		v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);1470		v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);1471		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);1472		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);1473		spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);1474		v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);1475 1476		return;1477	}1478	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE) {1479		if (ctx->source_change || mxc_jpeg_source_change(ctx, jpeg_src_buf)) {1480			spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);1481			v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);1482			return;1483		}1484	}1485 1486	mxc_jpeg_enable(reg);1487	mxc_jpeg_set_l_endian(reg, 1);1488 1489	ctx->slot = mxc_get_free_slot(&jpeg->slot_data);1490	if (ctx->slot < 0) {1491		dev_err(dev, "No more free slots\n");1492		goto end;1493	}1494	if (!mxc_jpeg_alloc_slot_data(jpeg)) {1495		dev_err(dev, "Cannot allocate slot data\n");1496		goto end;1497	}1498 1499	mxc_jpeg_enable_slot(reg, ctx->slot);1500	mxc_jpeg_enable_irq(reg, ctx->slot);1501 1502	if (jpeg->mode == MXC_JPEG_ENCODE) {1503		dev_dbg(dev, "Encoding on slot %d\n", ctx->slot);1504		ctx->enc_state = MXC_JPEG_ENC_CONF;1505		mxc_jpeg_config_enc_desc(&dst_buf->vb2_buf, ctx,1506					 &src_buf->vb2_buf, &dst_buf->vb2_buf);1507		/* start config phase */1508		mxc_jpeg_enc_mode_conf(dev, reg,1509				       mxc_jpeg_is_extended_sequential(q_data_out->fmt));1510	} else {1511		dev_dbg(dev, "Decoding on slot %d\n", ctx->slot);1512		print_mxc_buf(jpeg, &src_buf->vb2_buf, 0);1513		mxc_jpeg_config_dec_desc(&dst_buf->vb2_buf, ctx,1514					 &src_buf->vb2_buf, &dst_buf->vb2_buf);1515		mxc_jpeg_dec_mode_go(dev, reg);1516	}1517	schedule_delayed_work(&ctx->task_timer, msecs_to_jiffies(hw_timeout));1518end:1519	spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);1520}1521 1522static int mxc_jpeg_decoder_cmd(struct file *file, void *priv,1523				struct v4l2_decoder_cmd *cmd)1524{1525	struct v4l2_fh *fh = file->private_data;1526	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);1527	unsigned long flags;1528	int ret;1529 1530	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);1531	if (ret < 0)1532		return ret;1533 1534	if (!vb2_is_streaming(v4l2_m2m_get_src_vq(fh->m2m_ctx)))1535		return 0;1536 1537	spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);1538	ret = v4l2_m2m_ioctl_decoder_cmd(file, priv, cmd);1539	spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);1540	if (ret < 0)1541		return ret;1542 1543	if (cmd->cmd == V4L2_DEC_CMD_STOP &&1544	    v4l2_m2m_has_stopped(fh->m2m_ctx)) {1545		notify_eos(ctx);1546		ctx->header_parsed = false;1547	}1548 1549	if (cmd->cmd == V4L2_DEC_CMD_START &&1550	    v4l2_m2m_has_stopped(fh->m2m_ctx))1551		vb2_clear_last_buffer_dequeued(&fh->m2m_ctx->cap_q_ctx.q);1552	return 0;1553}1554 1555static int mxc_jpeg_encoder_cmd(struct file *file, void *priv,1556				struct v4l2_encoder_cmd *cmd)1557{1558	struct v4l2_fh *fh = file->private_data;1559	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);1560	unsigned long flags;1561	int ret;1562 1563	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, cmd);1564	if (ret < 0)1565		return ret;1566 1567	if (!vb2_is_streaming(v4l2_m2m_get_src_vq(fh->m2m_ctx)) ||1568	    !vb2_is_streaming(v4l2_m2m_get_dst_vq(fh->m2m_ctx)))1569		return 0;1570 1571	spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);1572	ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, cmd);1573	spin_unlock_irqrestore(&ctx->mxc_jpeg->hw_lock, flags);1574	if (ret < 0)1575		return 0;1576 1577	if (cmd->cmd == V4L2_ENC_CMD_STOP &&1578	    v4l2_m2m_has_stopped(fh->m2m_ctx))1579		notify_eos(ctx);1580 1581	if (cmd->cmd == V4L2_ENC_CMD_START &&1582	    v4l2_m2m_has_stopped(fh->m2m_ctx))1583		vb2_clear_last_buffer_dequeued(&fh->m2m_ctx->cap_q_ctx.q);1584 1585	return 0;1586}1587 1588static int mxc_jpeg_queue_setup(struct vb2_queue *q,1589				unsigned int *nbuffers,1590				unsigned int *nplanes,1591				unsigned int sizes[],1592				struct device *alloc_ctxs[])1593{1594	struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);1595	struct mxc_jpeg_q_data *q_data = NULL;1596	int i;1597 1598	q_data = mxc_jpeg_get_q_data(ctx, q->type);1599	if (!q_data)1600		return -EINVAL;1601 1602	/* Handle CREATE_BUFS situation - *nplanes != 0 */1603	if (*nplanes) {1604		if (*nplanes != q_data->fmt->mem_planes)1605			return -EINVAL;1606		for (i = 0; i < *nplanes; i++) {1607			if (sizes[i] < mxc_jpeg_get_plane_size(q_data, i))1608				return -EINVAL;1609		}1610		return 0;1611	}1612 1613	/* Handle REQBUFS situation */1614	*nplanes = q_data->fmt->mem_planes;1615	for (i = 0; i < *nplanes; i++)1616		sizes[i] = mxc_jpeg_get_plane_size(q_data, i);1617 1618	if (V4L2_TYPE_IS_OUTPUT(q->type))1619		ctx->need_initial_source_change_evt = true;1620 1621	return 0;1622}1623 1624static int mxc_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)1625{1626	struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);1627	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, q->type);1628	int ret;1629 1630	v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);1631 1632	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(q->type))1633		ctx->source_change = 0;1634	dev_dbg(ctx->mxc_jpeg->dev, "Start streaming ctx=%p", ctx);1635	q_data->sequence = 0;1636 1637	if (V4L2_TYPE_IS_CAPTURE(q->type))1638		ctx->need_initial_source_change_evt = false;1639 1640	ret = pm_runtime_resume_and_get(ctx->mxc_jpeg->dev);1641	if (ret < 0) {1642		dev_err(ctx->mxc_jpeg->dev, "Failed to power up jpeg\n");1643		return ret;1644	}1645 1646	return 0;1647}1648 1649static void mxc_jpeg_stop_streaming(struct vb2_queue *q)1650{1651	struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(q);1652	struct vb2_v4l2_buffer *vbuf;1653 1654	dev_dbg(ctx->mxc_jpeg->dev, "Stop streaming ctx=%p", ctx);1655 1656	/* Release all active buffers */1657	for (;;) {1658		if (V4L2_TYPE_IS_OUTPUT(q->type))1659			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);1660		else1661			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);1662		if (!vbuf)1663			break;1664		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);1665	}1666 1667	v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);1668	/* if V4L2_DEC_CMD_STOP is sent before the source change triggered,1669	 * restore the is_draining flag1670	 */1671	if (V4L2_TYPE_IS_CAPTURE(q->type) && ctx->source_change && ctx->fh.m2m_ctx->last_src_buf)1672		ctx->fh.m2m_ctx->is_draining = true;1673 1674	if (V4L2_TYPE_IS_OUTPUT(q->type) &&1675	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) {1676		notify_eos(ctx);1677		ctx->header_parsed = false;1678	}1679 1680	pm_runtime_put_sync(&ctx->mxc_jpeg->pdev->dev);1681}1682 1683static int mxc_jpeg_valid_comp_id(struct device *dev,1684				  struct mxc_jpeg_sof *sof,1685				  struct mxc_jpeg_sos *sos)1686{1687	int valid = 1;1688	int i;1689 1690	/*1691	 * there's a limitation in the IP that the component IDs must be1692	 * between 0..4, if they are not, let's patch them1693	 */1694	for (i = 0; i < sof->components_no; i++)1695		if (sof->comp[i].id > MXC_JPEG_MAX_COMPONENTS) {1696			valid = 0;1697			dev_err(dev, "Component %d has invalid ID: %d",1698				i, sof->comp[i].id);1699		}1700	if (!valid)1701		/* patch all comp IDs if at least one is invalid */1702		for (i = 0; i < sof->components_no; i++) {1703			dev_warn(dev, "Component %d ID patched to: %d",1704				 i, i + 1);1705			sof->comp[i].id = i + 1;1706			sos->comp[i].id = i + 1;1707		}1708 1709	return valid;1710}1711 1712static bool mxc_jpeg_match_image_format(const struct mxc_jpeg_fmt *fmt,1713					const struct v4l2_jpeg_header *header)1714{1715	if (fmt->subsampling != header->frame.subsampling ||1716	    fmt->nc != header->frame.num_components ||1717	    fmt->precision != header->frame.precision)1718		return false;1719 1720	/*1721	 * If the transform flag from APP14 marker is 0, images that are1722	 * encoded with 3 components have RGB colorspace, see Recommendation1723	 * ITU-T T.872 chapter 6.5.3 APP14 marker segment for colour encoding1724	 */1725	if (header->frame.subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_444) {1726		u8 is_rgb = header->app14_tf == V4L2_JPEG_APP14_TF_CMYK_RGB ? 1 : 0;1727 1728		if (is_rgb != fmt->is_rgb)1729			return false;1730	}1731	return true;1732}1733 1734static u32 mxc_jpeg_get_image_format(struct device *dev,1735				     const struct v4l2_jpeg_header *header)1736{1737	int i;1738	u32 fourcc = 0;1739 1740	for (i = 0; i < MXC_JPEG_NUM_FORMATS; i++) {1741		if (mxc_jpeg_match_image_format(&mxc_formats[i], header)) {1742			fourcc = mxc_formats[i].fourcc;1743			break;1744		}1745	}1746	if (fourcc == 0) {1747		dev_err(dev,1748			"Could not identify image format nc=%d, subsampling=%d, precision=%d\n",1749			header->frame.num_components,1750			header->frame.subsampling,1751			header->frame.precision);1752		return fourcc;1753	}1754 1755	return fourcc;1756}1757 1758static void mxc_jpeg_bytesperline(struct mxc_jpeg_q_data *q, u32 precision)1759{1760	u32 bytesperline[2];1761 1762	bytesperline[0] = q->bytesperline[0];1763	bytesperline[1] = q->bytesperline[0];	/*imx-jpeg only support the same line pitch*/1764	v4l_bound_align_image(&bytesperline[0], 0, MXC_JPEG_MAX_LINE, 2,1765			      &bytesperline[1], 0, MXC_JPEG_MAX_LINE, 2,1766			      0);1767 1768	/* Bytes distance between the leftmost pixels in two adjacent lines */1769	if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {1770		/* bytesperline unused for compressed formats */1771		q->bytesperline[0] = 0;1772		q->bytesperline[1] = 0;1773	} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420) {1774		/* When the image format is planar the bytesperline value1775		 * applies to the first plane and is divided by the same factor1776		 * as the width field for the other planes1777		 */1778		q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8);1779		q->bytesperline[1] = q->bytesperline[0];1780	} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422) {1781		q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8) * 2;1782		q->bytesperline[1] = 0;1783	} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_444) {1784		q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8) * q->fmt->nc;1785		q->bytesperline[1] = 0;1786	} else {1787		/* grayscale */1788		q->bytesperline[0] = q->w_adjusted * DIV_ROUND_UP(precision, 8);1789		q->bytesperline[1] = 0;1790	}1791 1792	if (q->fmt->fourcc != V4L2_PIX_FMT_JPEG) {1793		q->bytesperline[0] = max(q->bytesperline[0], bytesperline[0]);1794		if (q->fmt->mem_planes > 1)1795			q->bytesperline[1] = max(q->bytesperline[1], bytesperline[1]);1796	}1797}1798 1799static void mxc_jpeg_sizeimage(struct mxc_jpeg_q_data *q)1800{1801	if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {1802		/* if no sizeimage from user, assume worst jpeg compression */1803		if (!q->sizeimage[0])1804			q->sizeimage[0] = 6 * q->w * q->h;1805		q->sizeimage[1] = 0;1806 1807		if (q->sizeimage[0] > MXC_JPEG_MAX_SIZEIMAGE)1808			q->sizeimage[0] = MXC_JPEG_MAX_SIZEIMAGE;1809 1810		/* jpeg stream size must be multiple of 1K */1811		q->sizeimage[0] = ALIGN(q->sizeimage[0], 1024);1812	} else {1813		q->sizeimage[0] = q->bytesperline[0] * q->h_adjusted;1814		q->sizeimage[1] = 0;1815		if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420)1816			q->sizeimage[1] = q->sizeimage[0] / 2;1817	}1818}1819 1820static int mxc_jpeg_parse(struct mxc_jpeg_ctx *ctx, struct vb2_buffer *vb)1821{1822	struct device *dev = ctx->mxc_jpeg->dev;1823	struct mxc_jpeg_q_data *q_data_out;1824	struct mxc_jpeg_q_data *q_data_cap;1825	u32 fourcc;1826	struct v4l2_jpeg_header header;1827	struct mxc_jpeg_sof *psof = NULL;1828	struct mxc_jpeg_sos *psos = NULL;1829	struct mxc_jpeg_src_buf *jpeg_src_buf = vb2_to_mxc_buf(vb);1830	u8 *src_addr = (u8 *)vb2_plane_vaddr(vb, 0);1831	u32 size = vb2_get_plane_payload(vb, 0);1832	int ret;1833 1834	memset(&header, 0, sizeof(header));1835	ret = v4l2_jpeg_parse_header((void *)src_addr, size, &header);1836	if (ret < 0) {1837		dev_err(dev, "Error parsing JPEG stream markers\n");1838		return ret;1839	}1840 1841	/* if DHT marker present, no need to inject default one */1842	jpeg_src_buf->dht_needed = (header.num_dht == 0);1843 1844	q_data_out = mxc_jpeg_get_q_data(ctx,1845					 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);1846	q_data_out->w = header.frame.width;1847	q_data_out->h = header.frame.height;1848	if (header.frame.width > MXC_JPEG_MAX_WIDTH ||1849	    header.frame.height > MXC_JPEG_MAX_HEIGHT) {1850		dev_err(dev, "JPEG width or height should be <= 8192: %dx%d\n",1851			header.frame.width, header.frame.height);1852		return -EINVAL;1853	}1854	if (header.frame.width < MXC_JPEG_MIN_WIDTH ||1855	    header.frame.height < MXC_JPEG_MIN_HEIGHT) {1856		dev_err(dev, "JPEG width or height should be > 64: %dx%d\n",1857			header.frame.width, header.frame.height);1858		return -EINVAL;1859	}1860	if (header.frame.num_components > V4L2_JPEG_MAX_COMPONENTS) {1861		dev_err(dev, "JPEG number of components should be <=%d",1862			V4L2_JPEG_MAX_COMPONENTS);1863		return -EINVAL;1864	}1865	/* check and, if necessary, patch component IDs*/1866	psof = (struct mxc_jpeg_sof *)header.sof.start;1867	psos = (struct mxc_jpeg_sos *)header.sos.start;1868	if (!mxc_jpeg_valid_comp_id(dev, psof, psos))1869		dev_warn(dev, "JPEG component ids should be 0-3 or 1-4");1870 1871	q_data_cap = mxc_jpeg_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);1872	if (q_data_cap->fmt && mxc_jpeg_match_image_format(q_data_cap->fmt, &header))1873		fourcc = q_data_cap->fmt->fourcc;1874	else1875		fourcc = mxc_jpeg_get_image_format(dev, &header);1876	if (fourcc == 0)1877		return -EINVAL;1878 1879	jpeg_src_buf->fmt = mxc_jpeg_find_format(fourcc);1880	jpeg_src_buf->w = header.frame.width;1881	jpeg_src_buf->h = header.frame.height;1882	ctx->header_parsed = true;1883 1884	if (!v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx))1885		mxc_jpeg_source_change(ctx, jpeg_src_buf);1886 1887	return 0;1888}1889 1890static void mxc_jpeg_buf_queue(struct vb2_buffer *vb)1891{1892	int ret;1893	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1894	struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);1895	struct mxc_jpeg_src_buf *jpeg_src_buf;1896 1897	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&1898	    vb2_is_streaming(vb->vb2_queue) &&1899	    v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {1900		struct mxc_jpeg_q_data *q_data;1901 1902		q_data = mxc_jpeg_get_q_data(ctx, vb->vb2_queue->type);1903		vbuf->field = V4L2_FIELD_NONE;1904		vbuf->sequence = q_data->sequence++;1905		v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);1906		notify_eos(ctx);1907		ctx->header_parsed = false;1908		return;1909	}1910 1911	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)1912		goto end;1913 1914	/* for V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE */1915	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)1916		goto end;1917 1918	jpeg_src_buf = vb2_to_mxc_buf(vb);1919	jpeg_src_buf->jpeg_parse_error = false;1920	ret = mxc_jpeg_parse(ctx, vb);1921	if (ret)1922		jpeg_src_buf->jpeg_parse_error = true;1923 1924end:1925	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);1926}1927 1928static int mxc_jpeg_buf_out_validate(struct vb2_buffer *vb)1929{1930	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1931 1932	vbuf->field = V4L2_FIELD_NONE;1933 1934	return 0;1935}1936 1937static int mxc_jpeg_buf_prepare(struct vb2_buffer *vb)1938{1939	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1940	struct mxc_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);1941	struct mxc_jpeg_q_data *q_data = NULL;1942	struct device *dev = ctx->mxc_jpeg->dev;1943	unsigned long sizeimage;1944	int i;1945 1946	vbuf->field = V4L2_FIELD_NONE;1947 1948	q_data = mxc_jpeg_get_q_data(ctx, vb->vb2_queue->type);1949	if (!q_data)1950		return -EINVAL;1951	for (i = 0; i < q_data->fmt->mem_planes; i++) {1952		sizeimage = mxc_jpeg_get_plane_size(q_data, i);1953		if (!ctx->source_change && vb2_plane_size(vb, i) < sizeimage) {1954			dev_err(dev, "plane %d too small (%lu < %lu)",1955				i, vb2_plane_size(vb, i), sizeimage);1956			return -EINVAL;1957		}1958	}1959	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) {1960		vb2_set_plane_payload(vb, 0, 0);1961		vb2_set_plane_payload(vb, 1, 0);1962	}1963	return 0;1964}1965 1966static const struct vb2_ops mxc_jpeg_qops = {1967	.queue_setup		= mxc_jpeg_queue_setup,1968	.wait_prepare		= vb2_ops_wait_prepare,1969	.wait_finish		= vb2_ops_wait_finish,1970	.buf_out_validate	= mxc_jpeg_buf_out_validate,1971	.buf_prepare		= mxc_jpeg_buf_prepare,1972	.start_streaming	= mxc_jpeg_start_streaming,1973	.stop_streaming		= mxc_jpeg_stop_streaming,1974	.buf_queue		= mxc_jpeg_buf_queue,1975};1976 1977static int mxc_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,1978			       struct vb2_queue *dst_vq)1979{1980	struct mxc_jpeg_ctx *ctx = priv;1981	int ret;1982 1983	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;1984	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;1985	src_vq->drv_priv = ctx;1986	src_vq->buf_struct_size = sizeof(struct mxc_jpeg_src_buf);1987	src_vq->ops = &mxc_jpeg_qops;1988	src_vq->mem_ops = &vb2_dma_contig_memops;1989	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;1990	src_vq->lock = &ctx->mxc_jpeg->lock;1991	src_vq->dev = ctx->mxc_jpeg->dev;1992 1993	ret = vb2_queue_init(src_vq);1994	if (ret)1995		return ret;1996 1997	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;1998	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;1999	dst_vq->drv_priv = ctx;2000	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);2001	dst_vq->ops = &mxc_jpeg_qops;2002	dst_vq->mem_ops = &vb2_dma_contig_memops;2003	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;2004	dst_vq->lock = &ctx->mxc_jpeg->lock;2005	dst_vq->dev = ctx->mxc_jpeg->dev;2006 2007	ret = vb2_queue_init(dst_vq);2008	return ret;2009}2010 2011static void mxc_jpeg_set_default_params(struct mxc_jpeg_ctx *ctx)2012{2013	struct mxc_jpeg_q_data *out_q = &ctx->out_q;2014	struct mxc_jpeg_q_data *cap_q = &ctx->cap_q;2015	struct mxc_jpeg_q_data *q[2] = {out_q, cap_q};2016	int i;2017 2018	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {2019		out_q->fmt = mxc_jpeg_find_format(MXC_JPEG_DEFAULT_PFMT);2020		cap_q->fmt = mxc_jpeg_find_format(V4L2_PIX_FMT_JPEG);2021	} else {2022		out_q->fmt = mxc_jpeg_find_format(V4L2_PIX_FMT_JPEG);2023		cap_q->fmt = mxc_jpeg_find_format(MXC_JPEG_DEFAULT_PFMT);2024	}2025 2026	for (i = 0; i < 2; i++) {2027		q[i]->w = MXC_JPEG_DEFAULT_WIDTH;2028		q[i]->h = MXC_JPEG_DEFAULT_HEIGHT;2029		q[i]->w_adjusted = MXC_JPEG_DEFAULT_WIDTH;2030		q[i]->h_adjusted = MXC_JPEG_DEFAULT_HEIGHT;2031		q[i]->crop.left = 0;2032		q[i]->crop.top = 0;2033		q[i]->crop.width = MXC_JPEG_DEFAULT_WIDTH;2034		q[i]->crop.height = MXC_JPEG_DEFAULT_HEIGHT;2035		mxc_jpeg_bytesperline(q[i], q[i]->fmt->precision);2036		mxc_jpeg_sizeimage(q[i]);2037	}2038}2039 2040static int mxc_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)2041{2042	struct mxc_jpeg_ctx *ctx =2043		container_of(ctrl->handler, struct mxc_jpeg_ctx, ctrl_handler);2044 2045	switch (ctrl->id) {2046	case V4L2_CID_JPEG_COMPRESSION_QUALITY:2047		ctx->jpeg_quality = ctrl->val;2048		break;2049	default:2050		dev_err(ctx->mxc_jpeg->dev, "Invalid control, id = %d, val = %d\n",2051			ctrl->id, ctrl->val);2052		return -EINVAL;2053	}2054 2055	return 0;2056}2057 2058static const struct v4l2_ctrl_ops mxc_jpeg_ctrl_ops = {2059	.s_ctrl = mxc_jpeg_s_ctrl,2060};2061 2062static void mxc_jpeg_encode_ctrls(struct mxc_jpeg_ctx *ctx)2063{2064	v4l2_ctrl_new_std(&ctx->ctrl_handler, &mxc_jpeg_ctrl_ops,2065			  V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 75);2066}2067 2068static int mxc_jpeg_ctrls_setup(struct mxc_jpeg_ctx *ctx)2069{2070	int err;2071 2072	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 2);2073 2074	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE)2075		mxc_jpeg_encode_ctrls(ctx);2076 2077	if (ctx->ctrl_handler.error) {2078		err = ctx->ctrl_handler.error;2079 2080		v4l2_ctrl_handler_free(&ctx->ctrl_handler);2081		return err;2082	}2083 2084	err = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);2085	if (err)2086		v4l2_ctrl_handler_free(&ctx->ctrl_handler);2087	return err;2088}2089 2090static int mxc_jpeg_open(struct file *file)2091{2092	struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);2093	struct video_device *mxc_vfd = video_devdata(file);2094	struct device *dev = mxc_jpeg->dev;2095	struct mxc_jpeg_ctx *ctx;2096	int ret = 0;2097 2098	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);2099	if (!ctx)2100		return -ENOMEM;2101 2102	if (mutex_lock_interruptible(&mxc_jpeg->lock)) {2103		ret = -ERESTARTSYS;2104		goto free;2105	}2106 2107	v4l2_fh_init(&ctx->fh, mxc_vfd);2108	file->private_data = &ctx->fh;2109	v4l2_fh_add(&ctx->fh);2110 2111	ctx->mxc_jpeg = mxc_jpeg;2112 2113	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(mxc_jpeg->m2m_dev, ctx,2114					    mxc_jpeg_queue_init);2115 2116	if (IS_ERR(ctx->fh.m2m_ctx)) {2117		ret = PTR_ERR(ctx->fh.m2m_ctx);2118		goto error;2119	}2120 2121	ret = mxc_jpeg_ctrls_setup(ctx);2122	if (ret) {2123		dev_err(ctx->mxc_jpeg->dev, "failed to setup mxc jpeg controls\n");2124		goto err_ctrls_setup;2125	}2126	ctx->fh.ctrl_handler = &ctx->ctrl_handler;2127	mxc_jpeg_set_default_params(ctx);2128	ctx->slot = -1; /* slot not allocated yet */2129	INIT_DELAYED_WORK(&ctx->task_timer, mxc_jpeg_device_run_timeout);2130 2131	if (mxc_jpeg->mode == MXC_JPEG_DECODE)2132		dev_dbg(dev, "Opened JPEG decoder instance %p\n", ctx);2133	else2134		dev_dbg(dev, "Opened JPEG encoder instance %p\n", ctx);2135	mutex_unlock(&mxc_jpeg->lock);2136 2137	return 0;2138 2139err_ctrls_setup:2140	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);2141error:2142	v4l2_fh_del(&ctx->fh);2143	v4l2_fh_exit(&ctx->fh);2144	mutex_unlock(&mxc_jpeg->lock);2145free:2146	kfree(ctx);2147	return ret;2148}2149 2150static int mxc_jpeg_querycap(struct file *file, void *priv,2151			     struct v4l2_capability *cap)2152{2153	strscpy(cap->driver, MXC_JPEG_NAME " codec", sizeof(cap->driver));2154	strscpy(cap->card, MXC_JPEG_NAME " codec", sizeof(cap->card));2155	cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;2156	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;2157 2158	return 0;2159}2160 2161static int mxc_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,2162				     struct v4l2_fmtdesc *f)2163{2164	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);2165	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);2166 2167	if (ctx->mxc_jpeg->mode == MXC_JPEG_ENCODE) {2168		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,2169			MXC_JPEG_FMT_TYPE_ENC);2170	} else if (!ctx->header_parsed) {2171		return enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f,2172			MXC_JPEG_FMT_TYPE_RAW);2173	} else {2174		/* For the decoder CAPTURE queue, only enumerate the raw formats2175		 * supported for the format currently active on OUTPUT2176		 * (more precisely what was propagated on capture queue2177		 * after jpeg parse on the output buffer)2178		 */2179		int ret = -EINVAL;2180		const struct mxc_jpeg_fmt *sibling;2181 2182		switch (f->index) {2183		case 0:2184			f->pixelformat = q_data->fmt->fourcc;2185			ret = 0;2186			break;2187		case 1:2188			sibling = mxc_jpeg_get_sibling_format(q_data->fmt);2189			if (sibling) {2190				f->pixelformat = sibling->fourcc;2191				ret = 0;2192			}2193			break;2194		default:2195			break;2196		}2197		return ret;2198	}2199}2200 2201static int mxc_jpeg_enum_fmt_vid_out(struct file *file, void *priv,2202				     struct v4l2_fmtdesc *f)2203{2204	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);2205	u32 type = ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ?  MXC_JPEG_FMT_TYPE_ENC :2206							     MXC_JPEG_FMT_TYPE_RAW;2207	int ret;2208 2209	ret = enum_fmt(mxc_formats, MXC_JPEG_NUM_FORMATS, f, type);2210	if (ret)2211		return ret;2212	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)2213		f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION;2214	return 0;2215}2216 2217static u32 mxc_jpeg_get_fmt_type(struct mxc_jpeg_ctx *ctx, u32 type)2218{2219	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)2220		return V4L2_TYPE_IS_OUTPUT(type) ? MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW;2221	else2222		return V4L2_TYPE_IS_CAPTURE(type) ? MXC_JPEG_FMT_TYPE_ENC : MXC_JPEG_FMT_TYPE_RAW;2223}2224 2225static u32 mxc_jpeg_get_default_fourcc(struct mxc_jpeg_ctx *ctx, u32 type)2226{2227	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)2228		return V4L2_TYPE_IS_OUTPUT(type) ? V4L2_PIX_FMT_JPEG : MXC_JPEG_DEFAULT_PFMT;2229	else2230		return V4L2_TYPE_IS_CAPTURE(type) ? V4L2_PIX_FMT_JPEG : MXC_JPEG_DEFAULT_PFMT;2231}2232 2233static u32 mxc_jpeg_try_fourcc(struct mxc_jpeg_ctx *ctx, u32 fourcc)2234{2235	const struct mxc_jpeg_fmt *sibling;2236	struct mxc_jpeg_q_data *q_data_cap;2237 2238	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)2239		return fourcc;2240	if (!ctx->header_parsed)2241		return fourcc;2242 2243	q_data_cap = &ctx->cap_q;2244	if (q_data_cap->fmt->fourcc == fourcc)2245		return fourcc;2246 2247	sibling = mxc_jpeg_get_sibling_format(q_data_cap->fmt);2248	if (sibling && sibling->fourcc == fourcc)2249		return sibling->fourcc;2250 2251	return q_data_cap->fmt->fourcc;2252}2253 2254static int mxc_jpeg_try_fmt(struct v4l2_format *f,2255			    struct mxc_jpeg_ctx *ctx, struct mxc_jpeg_q_data *q_data)2256{2257	const struct mxc_jpeg_fmt *fmt;2258	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;2259	struct v4l2_plane_pix_format *pfmt;2260	u32 fourcc = f->fmt.pix_mp.pixelformat;2261	u32 w = (pix_mp->width < MXC_JPEG_MAX_WIDTH) ?2262		 pix_mp->width : MXC_JPEG_MAX_WIDTH;2263	u32 h = (pix_mp->height < MXC_JPEG_MAX_HEIGHT) ?2264		 pix_mp->height : MXC_JPEG_MAX_HEIGHT;2265	int i;2266 2267	fmt = mxc_jpeg_find_format(fourcc);2268	if (!fmt || fmt->flags != mxc_jpeg_get_fmt_type(ctx, f->type)) {2269		dev_warn(ctx->mxc_jpeg->dev, "Format not supported: %c%c%c%c, use the default.\n",2270			 (fourcc & 0xff),2271			 (fourcc >>  8) & 0xff,2272			 (fourcc >> 16) & 0xff,2273			 (fourcc >> 24) & 0xff);2274		fourcc = mxc_jpeg_get_default_fourcc(ctx, f->type);2275		fmt = mxc_jpeg_find_format(fourcc);2276		if (!fmt)2277			return -EINVAL;2278		f->fmt.pix_mp.pixelformat = fourcc;2279	}2280	q_data->fmt = fmt;2281 2282	memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));2283	pix_mp->field = V4L2_FIELD_NONE;2284	pix_mp->num_planes = fmt->mem_planes;2285	pix_mp->pixelformat = fmt->fourcc;2286 2287	q_data->w = w;2288	q_data->h = h;2289	q_data->w_adjusted = w;2290	q_data->h_adjusted = h;2291	v4l_bound_align_image(&q_data->w_adjusted,2292			      w, /* adjust upwards*/2293			      MXC_JPEG_MAX_WIDTH,2294			      fmt->h_align,2295			      &q_data->h_adjusted,2296			      h, /* adjust upwards*/2297			      MXC_JPEG_MAX_HEIGHT,2298			      fmt->v_align,2299			      0);2300	for (i = 0; i < pix_mp->num_planes; i++) {2301		pfmt = &pix_mp->plane_fmt[i];2302		q_data->bytesperline[i] = pfmt->bytesperline;2303		q_data->sizeimage[i] = pfmt->sizeimage;2304	}2305 2306	/* calculate bytesperline & sizeimage */2307	mxc_jpeg_bytesperline(q_data, fmt->precision);2308	mxc_jpeg_sizeimage(q_data);2309 2310	/* adjust user format according to our calculations */2311	for (i = 0; i < pix_mp->num_planes; i++) {2312		pfmt = &pix_mp->plane_fmt[i];2313		memset(pfmt->reserved, 0, sizeof(pfmt->reserved));2314		pfmt->bytesperline = q_data->bytesperline[i];2315		pfmt->sizeimage = mxc_jpeg_get_plane_size(q_data, i);2316	}2317 2318	/* fix colorspace information to sRGB for both output & capture */2319	pix_mp->colorspace = V4L2_COLORSPACE_SRGB;2320	pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;2321	pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;2322	/*2323	 * this hardware does not change the range of the samples2324	 * but since inside JPEG the YUV quantization is full-range,2325	 * this driver will always use full-range for the raw frames, too2326	 */2327	pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;2328 2329	if (fmt->flags == MXC_JPEG_FMT_TYPE_RAW) {2330		q_data->crop.left = 0;2331		q_data->crop.top = 0;2332		q_data->crop.width = q_data->w;2333		q_data->crop.height = q_data->h;2334	}2335 2336	pix_mp->width = q_data->w_adjusted;2337	pix_mp->height = q_data->h_adjusted;2338 2339	return 0;2340}2341 2342static int mxc_jpeg_try_fmt_vid_cap(struct file *file, void *priv,2343				    struct v4l2_format *f)2344{2345	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);2346	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;2347	struct device *dev = jpeg->dev;2348	struct mxc_jpeg_q_data tmp_q;2349 2350	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {2351		dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);2352		return -EINVAL;2353	}2354 2355	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE && V4L2_TYPE_IS_CAPTURE(f->type))2356		f->fmt.pix_mp.pixelformat = mxc_jpeg_try_fourcc(ctx, f->fmt.pix_mp.pixelformat);2357 2358	return mxc_jpeg_try_fmt(f, ctx, &tmp_q);2359}2360 2361static int mxc_jpeg_try_fmt_vid_out(struct file *file, void *priv,2362				    struct v4l2_format *f)2363{2364	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);2365	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;2366	struct device *dev = jpeg->dev;2367	struct mxc_jpeg_q_data tmp_q;2368 2369	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {2370		dev_err(dev, "TRY_FMT with Invalid type: %d\n", f->type);2371		return -EINVAL;2372	}2373 2374	return mxc_jpeg_try_fmt(f, ctx, &tmp_q);2375}2376 2377static void mxc_jpeg_s_parsed_fmt(struct mxc_jpeg_ctx *ctx, struct v4l2_format *f)2378{2379	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;2380	struct mxc_jpeg_q_data *q_data_cap;2381 2382	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE || !V4L2_TYPE_IS_CAPTURE(f->type))2383		return;2384	if (!ctx->header_parsed)2385		return;2386 2387	q_data_cap = mxc_jpeg_get_q_data(ctx, f->type);2388	pix_mp->pixelformat = mxc_jpeg_try_fourcc(ctx, pix_mp->pixelformat);2389	pix_mp->width = q_data_cap->w;2390	pix_mp->height = q_data_cap->h;2391}2392 2393static int mxc_jpeg_s_fmt(struct mxc_jpeg_ctx *ctx,2394			  struct v4l2_format *f)2395{2396	struct vb2_queue *vq;2397	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;2398 2399	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);2400	if (!vq)2401		return -EINVAL;2402 2403	if (vb2_is_busy(vq)) {2404		v4l2_err(&jpeg->v4l2_dev, "queue busy\n");2405		return -EBUSY;2406	}2407 2408	mxc_jpeg_s_parsed_fmt(ctx, f);2409 2410	return mxc_jpeg_try_fmt(f, ctx, mxc_jpeg_get_q_data(ctx, f->type));2411}2412 2413static int mxc_jpeg_s_fmt_vid_cap(struct file *file, void *priv,2414				  struct v4l2_format *f)2415{2416	return mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);2417}2418 2419static int mxc_jpeg_s_fmt_vid_out(struct file *file, void *priv,2420				  struct v4l2_format *f)2421{2422	int ret;2423	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);2424	struct vb2_queue *dst_vq;2425	struct mxc_jpeg_q_data *q_data_cap;2426	enum v4l2_buf_type cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;2427	struct v4l2_format fc;2428 2429	ret = mxc_jpeg_s_fmt(mxc_jpeg_fh_to_ctx(priv), f);2430	if (ret)2431		return ret;2432 2433	if (ctx->mxc_jpeg->mode != MXC_JPEG_DECODE)2434		return 0;2435 2436	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, cap_type);2437	if (!dst_vq)2438		return -EINVAL;2439 2440	if (vb2_is_busy(dst_vq))2441		return 0;2442 2443	q_data_cap = mxc_jpeg_get_q_data(ctx, cap_type);2444	if (q_data_cap->w == f->fmt.pix_mp.width && q_data_cap->h == f->fmt.pix_mp.height)2445		return 0;2446	memset(&fc, 0, sizeof(fc));2447	fc.type = cap_type;2448	fc.fmt.pix_mp.pixelformat = q_data_cap->fmt->fourcc;2449	fc.fmt.pix_mp.width = f->fmt.pix_mp.width;2450	fc.fmt.pix_mp.height = f->fmt.pix_mp.height;2451 2452	return mxc_jpeg_s_fmt_vid_cap(file, priv, &fc);2453}2454 2455static int mxc_jpeg_g_fmt_vid(struct file *file, void *priv,2456			      struct v4l2_format *f)2457{2458	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(priv);2459	struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;2460	struct device *dev = jpeg->dev;2461	struct v4l2_pix_format_mplane   *pix_mp = &f->fmt.pix_mp;2462	struct mxc_jpeg_q_data *q_data = mxc_jpeg_get_q_data(ctx, f->type);2463	int i;2464 2465	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {2466		dev_err(dev, "G_FMT with Invalid type: %d\n", f->type);2467		return -EINVAL;2468	}2469 2470	pix_mp->pixelformat = q_data->fmt->fourcc;2471	pix_mp->width = q_data->w;2472	pix_mp->height = q_data->h;2473	pix_mp->field = V4L2_FIELD_NONE;2474	if (q_data->fmt->flags == MXC_JPEG_FMT_TYPE_RAW) {2475		pix_mp->width = q_data->w_adjusted;2476		pix_mp->height = q_data->h_adjusted;2477	}2478 2479	/* fix colorspace information to sRGB for both output & capture */2480	pix_mp->colorspace = V4L2_COLORSPACE_SRGB;2481	pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_601;2482	pix_mp->xfer_func = V4L2_XFER_FUNC_SRGB;2483	pix_mp->quantization = V4L2_QUANTIZATION_FULL_RANGE;2484 2485	pix_mp->num_planes = q_data->fmt->mem_planes;2486	for (i = 0; i < pix_mp->num_planes; i++) {2487		pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i];2488		pix_mp->plane_fmt[i].sizeimage = mxc_jpeg_get_plane_size(q_data, i);2489	}2490 2491	return 0;2492}2493 2494static int mxc_jpeg_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)2495{2496	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);2497	struct mxc_jpeg_q_data *q_data_cap;2498 2499	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)2500		return -EINVAL;2501 2502	q_data_cap = mxc_jpeg_get_q_data(ctx, s->type);2503 2504	switch (s->target) {2505	case V4L2_SEL_TGT_COMPOSE:2506	case V4L2_SEL_TGT_COMPOSE_DEFAULT:2507		s->r = q_data_cap->crop;2508		break;2509	case V4L2_SEL_TGT_COMPOSE_PADDED:2510	case V4L2_SEL_TGT_COMPOSE_BOUNDS:2511		s->r.left = 0;2512		s->r.top = 0;2513		s->r.width = q_data_cap->w_adjusted;2514		s->r.height = q_data_cap->h_adjusted;2515		break;2516	default:2517		return -EINVAL;2518	}2519 2520	return 0;2521}2522 2523static int mxc_jpeg_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)2524{2525	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);2526	struct mxc_jpeg_q_data *q_data_out;2527 2528	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)2529		return -EINVAL;2530 2531	q_data_out = mxc_jpeg_get_q_data(ctx, s->type);2532 2533	switch (s->target) {2534	case V4L2_SEL_TGT_CROP_DEFAULT:2535	case V4L2_SEL_TGT_CROP_BOUNDS:2536		s->r.left = 0;2537		s->r.top = 0;2538		s->r.width = q_data_out->w;2539		s->r.height = q_data_out->h;2540		break;2541	case V4L2_SEL_TGT_CROP:2542		s->r = q_data_out->crop;2543		break;2544	default:2545		return -EINVAL;2546	}2547 2548	return 0;2549}2550 2551static int mxc_jpeg_g_selection(struct file *file, void *fh, struct v4l2_selection *s)2552{2553	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);2554 2555	if (ctx->mxc_jpeg->mode == MXC_JPEG_DECODE)2556		return mxc_jpeg_dec_g_selection(file, fh, s);2557	else2558		return mxc_jpeg_enc_g_selection(file, fh, s);2559}2560 2561static int mxc_jpeg_s_selection(struct file *file, void *fh, struct v4l2_selection *s)2562{2563	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(fh);2564	struct mxc_jpeg_q_data *q_data_out;2565 2566	if (ctx->mxc_jpeg->mode != MXC_JPEG_ENCODE)2567		return -ENOTTY;2568 2569	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)2570		return -EINVAL;2571	if (s->target != V4L2_SEL_TGT_CROP)2572		return -EINVAL;2573 2574	q_data_out = mxc_jpeg_get_q_data(ctx, s->type);2575	if (s->r.left || s->r.top)2576		return -EINVAL;2577	if (s->r.width > q_data_out->w || s->r.height > q_data_out->h)2578		return -EINVAL;2579 2580	q_data_out->crop.left = 0;2581	q_data_out->crop.top = 0;2582	q_data_out->crop.width = s->r.width;2583	q_data_out->crop.height = s->r.height;2584 2585	return 0;2586}2587 2588static int mxc_jpeg_subscribe_event(struct v4l2_fh *fh,2589				    const struct v4l2_event_subscription *sub)2590{2591	switch (sub->type) {2592	case V4L2_EVENT_EOS:2593		return v4l2_event_subscribe(fh, sub, 0, NULL);2594	case V4L2_EVENT_SOURCE_CHANGE:2595		return v4l2_src_change_event_subscribe(fh, sub);2596	case V4L2_EVENT_CTRL:2597		return v4l2_ctrl_subscribe_event(fh, sub);2598	default:2599		return -EINVAL;2600	}2601}2602 2603static const struct v4l2_ioctl_ops mxc_jpeg_ioctl_ops = {2604	.vidioc_querycap		= mxc_jpeg_querycap,2605	.vidioc_enum_fmt_vid_cap	= mxc_jpeg_enum_fmt_vid_cap,2606	.vidioc_enum_fmt_vid_out	= mxc_jpeg_enum_fmt_vid_out,2607 2608	.vidioc_try_fmt_vid_cap_mplane	= mxc_jpeg_try_fmt_vid_cap,2609	.vidioc_try_fmt_vid_out_mplane	= mxc_jpeg_try_fmt_vid_out,2610 2611	.vidioc_s_fmt_vid_cap_mplane	= mxc_jpeg_s_fmt_vid_cap,2612	.vidioc_s_fmt_vid_out_mplane	= mxc_jpeg_s_fmt_vid_out,2613 2614	.vidioc_g_fmt_vid_cap_mplane	= mxc_jpeg_g_fmt_vid,2615	.vidioc_g_fmt_vid_out_mplane	= mxc_jpeg_g_fmt_vid,2616 2617	.vidioc_g_selection		= mxc_jpeg_g_selection,2618	.vidioc_s_selection		= mxc_jpeg_s_selection,2619 2620	.vidioc_subscribe_event		= mxc_jpeg_subscribe_event,2621	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,2622 2623	.vidioc_try_decoder_cmd		= v4l2_m2m_ioctl_try_decoder_cmd,2624	.vidioc_decoder_cmd		= mxc_jpeg_decoder_cmd,2625	.vidioc_try_encoder_cmd		= v4l2_m2m_ioctl_try_encoder_cmd,2626	.vidioc_encoder_cmd		= mxc_jpeg_encoder_cmd,2627 2628	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,2629	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,2630 2631	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,2632	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,2633	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,2634	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,2635	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,2636	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,2637	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,2638};2639 2640static int mxc_jpeg_release(struct file *file)2641{2642	struct mxc_jpeg_dev *mxc_jpeg = video_drvdata(file);2643	struct mxc_jpeg_ctx *ctx = mxc_jpeg_fh_to_ctx(file->private_data);2644	struct device *dev = mxc_jpeg->dev;2645 2646	mutex_lock(&mxc_jpeg->lock);2647	if (mxc_jpeg->mode == MXC_JPEG_DECODE)2648		dev_dbg(dev, "Release JPEG decoder instance on slot %d.",2649			ctx->slot);2650	else2651		dev_dbg(dev, "Release JPEG encoder instance on slot %d.",2652			ctx->slot);2653	v4l2_ctrl_handler_free(&ctx->ctrl_handler);2654	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);2655	v4l2_fh_del(&ctx->fh);2656	v4l2_fh_exit(&ctx->fh);2657	kfree(ctx);2658	mutex_unlock(&mxc_jpeg->lock);2659 2660	return 0;2661}2662 2663static const struct v4l2_file_operations mxc_jpeg_fops = {2664	.owner		= THIS_MODULE,2665	.open		= mxc_jpeg_open,2666	.release	= mxc_jpeg_release,2667	.poll		= v4l2_m2m_fop_poll,2668	.unlocked_ioctl	= video_ioctl2,2669	.mmap		= v4l2_m2m_fop_mmap,2670};2671 2672static const struct v4l2_m2m_ops mxc_jpeg_m2m_ops = {2673	.job_ready      = mxc_jpeg_job_ready,2674	.device_run	= mxc_jpeg_device_run,2675};2676 2677static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)2678{2679	int i;2680 2681	for (i = 0; i < jpeg->num_domains; i++) {2682		if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i]))2683			device_link_del(jpeg->pd_link[i]);2684		if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i]))2685			dev_pm_domain_detach(jpeg->pd_dev[i], true);2686		jpeg->pd_dev[i] = NULL;2687		jpeg->pd_link[i] = NULL;2688	}2689}2690 2691static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)2692{2693	struct device *dev = jpeg->dev;2694	struct device_node *np = jpeg->pdev->dev.of_node;2695	int i;2696	int ret;2697 2698	jpeg->num_domains = of_count_phandle_with_args(np, "power-domains",2699						       "#power-domain-cells");2700	if (jpeg->num_domains < 0) {2701		dev_err(dev, "No power domains defined for jpeg node\n");2702		return jpeg->num_domains;2703	}2704	if (jpeg->num_domains == 1) {2705		/* genpd_dev_pm_attach() attach automatically if power domains count is 1 */2706		jpeg->num_domains = 0;2707		return 0;2708	}2709 2710	jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,2711					  sizeof(*jpeg->pd_dev), GFP_KERNEL);2712	if (!jpeg->pd_dev)2713		return -ENOMEM;2714 2715	jpeg->pd_link = devm_kmalloc_array(dev, jpeg->num_domains,2716					   sizeof(*jpeg->pd_link), GFP_KERNEL);2717	if (!jpeg->pd_link)2718		return -ENOMEM;2719 2720	for (i = 0; i < jpeg->num_domains; i++) {2721		jpeg->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);2722		if (IS_ERR(jpeg->pd_dev[i])) {2723			ret = PTR_ERR(jpeg->pd_dev[i]);2724			goto fail;2725		}2726 2727		jpeg->pd_link[i] = device_link_add(dev, jpeg->pd_dev[i],2728						   DL_FLAG_STATELESS |2729						   DL_FLAG_PM_RUNTIME);2730		if (!jpeg->pd_link[i]) {2731			ret = -EINVAL;2732			goto fail;2733		}2734	}2735 2736	return 0;2737fail:2738	mxc_jpeg_detach_pm_domains(jpeg);2739	return ret;2740}2741 2742static int mxc_jpeg_probe(struct platform_device *pdev)2743{2744	struct mxc_jpeg_dev *jpeg;2745	struct device *dev = &pdev->dev;2746	int dec_irq;2747	int ret;2748	int mode;2749	const struct of_device_id *of_id;2750 2751	of_id = of_match_node(mxc_jpeg_match, dev->of_node);2752	if (!of_id)2753		return -ENODEV;2754	mode = *(const int *)of_id->data;2755 2756	jpeg = devm_kzalloc(dev, sizeof(struct mxc_jpeg_dev), GFP_KERNEL);2757	if (!jpeg)2758		return -ENOMEM;2759 2760	mutex_init(&jpeg->lock);2761	spin_lock_init(&jpeg->hw_lock);2762 2763	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));2764	if (ret) {2765		dev_err(&pdev->dev, "No suitable DMA available.\n");2766		goto err_irq;2767	}2768 2769	jpeg->base_reg = devm_platform_ioremap_resource(pdev, 0);2770	if (IS_ERR(jpeg->base_reg))2771		return PTR_ERR(jpeg->base_reg);2772 2773	ret = of_property_read_u32_index(pdev->dev.of_node, "slot", 0, &jpeg->slot_data.slot);2774	if (ret)2775		jpeg->slot_data.slot = 0;2776	dev_info(&pdev->dev, "choose slot %d\n", jpeg->slot_data.slot);2777	dec_irq = platform_get_irq(pdev, 0);2778	if (dec_irq < 0) {2779		ret = dec_irq;2780		goto err_irq;2781	}2782	ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,2783			       0, pdev->name, jpeg);2784	if (ret) {2785		dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",2786			dec_irq, ret);2787		goto err_irq;2788	}2789 2790	jpeg->pdev = pdev;2791	jpeg->dev = dev;2792	jpeg->mode = mode;2793 2794	/* Get clocks */2795	ret = devm_clk_bulk_get_all(&pdev->dev, &jpeg->clks);2796	if (ret < 0) {2797		dev_err(dev, "failed to get clock\n");2798		goto err_clk;2799	}2800	jpeg->num_clks = ret;2801 2802	ret = mxc_jpeg_attach_pm_domains(jpeg);2803	if (ret < 0) {2804		dev_err(dev, "failed to attach power domains %d\n", ret);2805		goto err_clk;2806	}2807 2808	/* v4l2 */2809	ret = v4l2_device_register(dev, &jpeg->v4l2_dev);2810	if (ret) {2811		dev_err(dev, "failed to register v4l2 device\n");2812		goto err_register;2813	}2814	jpeg->m2m_dev = v4l2_m2m_init(&mxc_jpeg_m2m_ops);2815	if (IS_ERR(jpeg->m2m_dev)) {2816		dev_err(dev, "failed to register v4l2 device\n");2817		ret = PTR_ERR(jpeg->m2m_dev);2818		goto err_m2m;2819	}2820 2821	jpeg->dec_vdev = video_device_alloc();2822	if (!jpeg->dec_vdev) {2823		dev_err(dev, "failed to register v4l2 device\n");2824		ret = -ENOMEM;2825		goto err_vdev_alloc;2826	}2827	if (mode == MXC_JPEG_ENCODE)2828		snprintf(jpeg->dec_vdev->name,2829			 sizeof(jpeg->dec_vdev->name),2830			 "%s-enc", MXC_JPEG_NAME);2831	else2832		snprintf(jpeg->dec_vdev->name,2833			 sizeof(jpeg->dec_vdev->name),2834			 "%s-dec", MXC_JPEG_NAME);2835 2836	jpeg->dec_vdev->fops = &mxc_jpeg_fops;2837	jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;2838	jpeg->dec_vdev->minor = -1;2839	jpeg->dec_vdev->release = video_device_release;2840	jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */2841	jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;2842	jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;2843	jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |2844					V4L2_CAP_VIDEO_M2M_MPLANE;2845	if (mode == MXC_JPEG_ENCODE) {2846		v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_DECODER_CMD);2847		v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD);2848	} else {2849		v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_ENCODER_CMD);2850		v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_ENCODER_CMD);2851	}2852	ret = video_register_device(jpeg->dec_vdev, VFL_TYPE_VIDEO, -1);2853	if (ret) {2854		dev_err(dev, "failed to register video device\n");2855		goto err_vdev_register;2856	}2857	video_set_drvdata(jpeg->dec_vdev, jpeg);2858	if (mode == MXC_JPEG_ENCODE)2859		v4l2_info(&jpeg->v4l2_dev,2860			  "encoder device registered as /dev/video%d (%d,%d)\n",2861			  jpeg->dec_vdev->num, VIDEO_MAJOR,2862			  jpeg->dec_vdev->minor);2863	else2864		v4l2_info(&jpeg->v4l2_dev,2865			  "decoder device registered as /dev/video%d (%d,%d)\n",2866			  jpeg->dec_vdev->num, VIDEO_MAJOR,2867			  jpeg->dec_vdev->minor);2868 2869	platform_set_drvdata(pdev, jpeg);2870	pm_runtime_enable(dev);2871 2872	return 0;2873 2874err_vdev_register:2875	video_device_release(jpeg->dec_vdev);2876 2877err_vdev_alloc:2878	v4l2_m2m_release(jpeg->m2m_dev);2879 2880err_m2m:2881	v4l2_device_unregister(&jpeg->v4l2_dev);2882 2883err_register:2884	mxc_jpeg_detach_pm_domains(jpeg);2885 2886err_irq:2887err_clk:2888	return ret;2889}2890 2891#ifdef CONFIG_PM2892static int mxc_jpeg_runtime_resume(struct device *dev)2893{2894	struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);2895	int ret;2896 2897	ret = clk_bulk_prepare_enable(jpeg->num_clks, jpeg->clks);2898	if (ret < 0) {2899		dev_err(dev, "failed to enable clock\n");2900		return ret;2901	}2902 2903	return 0;2904}2905 2906static int mxc_jpeg_runtime_suspend(struct device *dev)2907{2908	struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);2909 2910	clk_bulk_disable_unprepare(jpeg->num_clks, jpeg->clks);2911 2912	return 0;2913}2914#endif2915 2916#ifdef CONFIG_PM_SLEEP2917static int mxc_jpeg_suspend(struct device *dev)2918{2919	struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);2920 2921	v4l2_m2m_suspend(jpeg->m2m_dev);2922	return pm_runtime_force_suspend(dev);2923}2924 2925static int mxc_jpeg_resume(struct device *dev)2926{2927	struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);2928	int ret;2929 2930	ret = pm_runtime_force_resume(dev);2931	if (ret < 0)2932		return ret;2933 2934	v4l2_m2m_resume(jpeg->m2m_dev);2935	return ret;2936}2937#endif2938 2939static const struct dev_pm_ops	mxc_jpeg_pm_ops = {2940	SET_RUNTIME_PM_OPS(mxc_jpeg_runtime_suspend,2941			   mxc_jpeg_runtime_resume, NULL)2942	SET_SYSTEM_SLEEP_PM_OPS(mxc_jpeg_suspend, mxc_jpeg_resume)2943};2944 2945static void mxc_jpeg_remove(struct platform_device *pdev)2946{2947	struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);2948 2949	mxc_jpeg_free_slot_data(jpeg);2950 2951	pm_runtime_disable(&pdev->dev);2952	video_unregister_device(jpeg->dec_vdev);2953	v4l2_m2m_release(jpeg->m2m_dev);2954	v4l2_device_unregister(&jpeg->v4l2_dev);2955	mxc_jpeg_detach_pm_domains(jpeg);2956}2957 2958MODULE_DEVICE_TABLE(of, mxc_jpeg_match);2959 2960static struct platform_driver mxc_jpeg_driver = {2961	.probe = mxc_jpeg_probe,2962	.remove_new = mxc_jpeg_remove,2963	.driver = {2964		.name = "mxc-jpeg",2965		.of_match_table = mxc_jpeg_match,2966		.pm = &mxc_jpeg_pm_ops,2967	},2968};2969module_platform_driver(mxc_jpeg_driver);2970 2971MODULE_AUTHOR("Zhengyu Shen <zhengyu.shen_1@nxp.com>");2972MODULE_AUTHOR("Mirela Rabulea <mirela.rabulea@nxp.com>");2973MODULE_DESCRIPTION("V4L2 driver for i.MX8 QXP/QM JPEG encoder/decoder");2974MODULE_LICENSE("GPL v2");2975