brintos

brintos / linux-shallow public Read only

0
0
Text · 83.5 KiB · 1db4609 Raw
3182 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c3 *4 * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.5 *		http://www.samsung.com6 *7 * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>8 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>9 */10 11#include <linux/clk.h>12#include <linux/err.h>13#include <linux/gfp.h>14#include <linux/interrupt.h>15#include <linux/io.h>16#include <linux/kernel.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/platform_device.h>20#include <linux/pm_runtime.h>21#include <linux/slab.h>22#include <linux/spinlock.h>23#include <linux/string.h>24#include <media/v4l2-event.h>25#include <media/v4l2-mem2mem.h>26#include <media/v4l2-ioctl.h>27#include <media/v4l2-rect.h>28#include <media/videobuf2-v4l2.h>29#include <media/videobuf2-dma-contig.h>30 31#include "jpeg-core.h"32#include "jpeg-hw-s5p.h"33#include "jpeg-hw-exynos4.h"34#include "jpeg-hw-exynos3250.h"35#include "jpeg-regs.h"36 37static struct s5p_jpeg_fmt sjpeg_formats[] = {38	{39		.fourcc		= V4L2_PIX_FMT_JPEG,40		.flags		= SJPEG_FMT_FLAG_ENC_CAPTURE |41				  SJPEG_FMT_FLAG_DEC_OUTPUT |42				  SJPEG_FMT_FLAG_S5P |43				  SJPEG_FMT_FLAG_EXYNOS3250 |44				  SJPEG_FMT_FLAG_EXYNOS4,45	},46	{47		.fourcc		= V4L2_PIX_FMT_YUYV,48		.depth		= 16,49		.colplanes	= 1,50		.h_align	= 4,51		.v_align	= 3,52		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |53				  SJPEG_FMT_FLAG_DEC_CAPTURE |54				  SJPEG_FMT_FLAG_S5P |55				  SJPEG_FMT_NON_RGB,56		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,57	},58	{59		.fourcc		= V4L2_PIX_FMT_YUYV,60		.depth		= 16,61		.colplanes	= 1,62		.h_align	= 1,63		.v_align	= 0,64		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |65				  SJPEG_FMT_FLAG_DEC_CAPTURE |66				  SJPEG_FMT_FLAG_EXYNOS4 |67				  SJPEG_FMT_NON_RGB,68		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,69	},70	{71		.fourcc		= V4L2_PIX_FMT_YUYV,72		.depth		= 16,73		.colplanes	= 1,74		.h_align	= 2,75		.v_align	= 0,76		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |77				  SJPEG_FMT_FLAG_DEC_CAPTURE |78				  SJPEG_FMT_FLAG_EXYNOS3250 |79				  SJPEG_FMT_NON_RGB,80		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,81	},82	{83		.fourcc		= V4L2_PIX_FMT_YVYU,84		.depth		= 16,85		.colplanes	= 1,86		.h_align	= 1,87		.v_align	= 0,88		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |89				  SJPEG_FMT_FLAG_DEC_CAPTURE |90				  SJPEG_FMT_FLAG_EXYNOS4 |91				  SJPEG_FMT_NON_RGB,92		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,93	},94	{95		.fourcc		= V4L2_PIX_FMT_YVYU,96		.depth		= 16,97		.colplanes	= 1,98		.h_align	= 2,99		.v_align	= 0,100		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |101				  SJPEG_FMT_FLAG_DEC_CAPTURE |102				  SJPEG_FMT_FLAG_EXYNOS3250 |103				  SJPEG_FMT_NON_RGB,104		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,105	},106	{107		.fourcc		= V4L2_PIX_FMT_UYVY,108		.depth		= 16,109		.colplanes	= 1,110		.h_align	= 2,111		.v_align	= 0,112		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |113				  SJPEG_FMT_FLAG_DEC_CAPTURE |114				  SJPEG_FMT_FLAG_EXYNOS3250 |115				  SJPEG_FMT_NON_RGB,116		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,117	},118	{119		.fourcc		= V4L2_PIX_FMT_VYUY,120		.depth		= 16,121		.colplanes	= 1,122		.h_align	= 2,123		.v_align	= 0,124		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |125				  SJPEG_FMT_FLAG_DEC_CAPTURE |126				  SJPEG_FMT_FLAG_EXYNOS3250 |127				  SJPEG_FMT_NON_RGB,128		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,129	},130	{131		.fourcc		= V4L2_PIX_FMT_RGB565,132		.depth		= 16,133		.colplanes	= 1,134		.h_align	= 0,135		.v_align	= 0,136		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |137				  SJPEG_FMT_FLAG_DEC_CAPTURE |138				  SJPEG_FMT_FLAG_EXYNOS4 |139				  SJPEG_FMT_RGB,140		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,141	},142	{143		.fourcc		= V4L2_PIX_FMT_RGB565,144		.depth		= 16,145		.colplanes	= 1,146		.h_align	= 2,147		.v_align	= 0,148		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |149				  SJPEG_FMT_FLAG_DEC_CAPTURE |150				  SJPEG_FMT_FLAG_EXYNOS3250 |151				  SJPEG_FMT_RGB,152		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,153	},154	{155		.fourcc		= V4L2_PIX_FMT_RGB565X,156		.depth		= 16,157		.colplanes	= 1,158		.h_align	= 2,159		.v_align	= 0,160		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |161				  SJPEG_FMT_FLAG_DEC_CAPTURE |162				  SJPEG_FMT_FLAG_EXYNOS3250 |163				  SJPEG_FMT_RGB,164		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,165	},166	{167		.fourcc		= V4L2_PIX_FMT_RGB565,168		.depth		= 16,169		.colplanes	= 1,170		.h_align	= 0,171		.v_align	= 0,172		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |173				  SJPEG_FMT_FLAG_S5P |174				  SJPEG_FMT_RGB,175		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,176	},177	{178		.fourcc		= V4L2_PIX_FMT_RGB32,179		.depth		= 32,180		.colplanes	= 1,181		.h_align	= 0,182		.v_align	= 0,183		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |184				  SJPEG_FMT_FLAG_DEC_CAPTURE |185				  SJPEG_FMT_FLAG_EXYNOS4 |186				  SJPEG_FMT_RGB,187		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,188	},189	{190		.fourcc		= V4L2_PIX_FMT_RGB32,191		.depth		= 32,192		.colplanes	= 1,193		.h_align	= 2,194		.v_align	= 0,195		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |196				  SJPEG_FMT_FLAG_DEC_CAPTURE |197				  SJPEG_FMT_FLAG_EXYNOS3250 |198				  SJPEG_FMT_RGB,199		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,200	},201	{202		.fourcc		= V4L2_PIX_FMT_NV24,203		.depth		= 24,204		.colplanes	= 2,205		.h_align	= 0,206		.v_align	= 0,207		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |208				  SJPEG_FMT_FLAG_DEC_CAPTURE |209				  SJPEG_FMT_FLAG_EXYNOS4 |210				  SJPEG_FMT_NON_RGB,211		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,212	},213	{214		.fourcc		= V4L2_PIX_FMT_NV42,215		.depth		= 24,216		.colplanes	= 2,217		.h_align	= 0,218		.v_align	= 0,219		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |220				  SJPEG_FMT_FLAG_DEC_CAPTURE |221				  SJPEG_FMT_FLAG_EXYNOS4 |222				  SJPEG_FMT_NON_RGB,223		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_444,224	},225	{226		.fourcc		= V4L2_PIX_FMT_NV61,227		.depth		= 16,228		.colplanes	= 2,229		.h_align	= 1,230		.v_align	= 0,231		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |232				  SJPEG_FMT_FLAG_DEC_CAPTURE |233				  SJPEG_FMT_FLAG_EXYNOS4 |234				  SJPEG_FMT_NON_RGB,235		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,236	},237	{238		.fourcc		= V4L2_PIX_FMT_NV16,239		.depth		= 16,240		.colplanes	= 2,241		.h_align	= 1,242		.v_align	= 0,243		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |244				  SJPEG_FMT_FLAG_DEC_CAPTURE |245				  SJPEG_FMT_FLAG_EXYNOS4 |246				  SJPEG_FMT_NON_RGB,247		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_422,248	},249	{250		.fourcc		= V4L2_PIX_FMT_NV12,251		.depth		= 12,252		.colplanes	= 2,253		.h_align	= 1,254		.v_align	= 1,255		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |256				  SJPEG_FMT_FLAG_DEC_CAPTURE |257				  SJPEG_FMT_FLAG_EXYNOS4 |258				  SJPEG_FMT_NON_RGB,259		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,260	},261	{262		.fourcc		= V4L2_PIX_FMT_NV12,263		.depth		= 12,264		.colplanes	= 2,265		.h_align	= 3,266		.v_align	= 3,267		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |268				  SJPEG_FMT_FLAG_DEC_CAPTURE |269				  SJPEG_FMT_FLAG_EXYNOS3250 |270				  SJPEG_FMT_NON_RGB,271		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,272	},273	{274		.fourcc		= V4L2_PIX_FMT_NV12,275		.depth		= 12,276		.colplanes	= 2,277		.h_align	= 4,278		.v_align	= 4,279		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |280				  SJPEG_FMT_FLAG_DEC_CAPTURE |281				  SJPEG_FMT_FLAG_S5P |282				  SJPEG_FMT_NON_RGB,283		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,284	},285	{286		.fourcc		= V4L2_PIX_FMT_NV21,287		.depth		= 12,288		.colplanes	= 2,289		.h_align	= 3,290		.v_align	= 3,291		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |292				  SJPEG_FMT_FLAG_DEC_CAPTURE |293				  SJPEG_FMT_FLAG_EXYNOS3250 |294				  SJPEG_FMT_NON_RGB,295		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,296	},297	{298		.fourcc		= V4L2_PIX_FMT_NV21,299		.depth		= 12,300		.colplanes	= 2,301		.h_align	= 1,302		.v_align	= 1,303		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |304				  SJPEG_FMT_FLAG_DEC_CAPTURE |305				  SJPEG_FMT_FLAG_EXYNOS3250 |306				  SJPEG_FMT_FLAG_EXYNOS4 |307				  SJPEG_FMT_NON_RGB,308		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,309	},310	{311		.fourcc		= V4L2_PIX_FMT_YUV420,312		.depth		= 12,313		.colplanes	= 3,314		.h_align	= 1,315		.v_align	= 1,316		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |317				  SJPEG_FMT_FLAG_DEC_CAPTURE |318				  SJPEG_FMT_FLAG_EXYNOS4 |319				  SJPEG_FMT_NON_RGB,320		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,321	},322	{323		.fourcc		= V4L2_PIX_FMT_YUV420,324		.depth		= 12,325		.colplanes	= 3,326		.h_align	= 4,327		.v_align	= 4,328		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |329				  SJPEG_FMT_FLAG_DEC_CAPTURE |330				  SJPEG_FMT_FLAG_EXYNOS3250 |331				  SJPEG_FMT_NON_RGB,332		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_420,333	},334	{335		.fourcc		= V4L2_PIX_FMT_GREY,336		.depth		= 8,337		.colplanes	= 1,338		.flags		= SJPEG_FMT_FLAG_ENC_OUTPUT |339				  SJPEG_FMT_FLAG_DEC_CAPTURE |340				  SJPEG_FMT_FLAG_EXYNOS4 |341				  SJPEG_FMT_NON_RGB,342		.subsampling	= V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,343	},344};345#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)346 347static const unsigned char qtbl_luminance[4][64] = {348	{/*level 0 - high compression quality */349		20, 16, 25, 39, 50, 46, 62, 68,350		16, 18, 23, 38, 38, 53, 65, 68,351		25, 23, 31, 38, 53, 65, 68, 68,352		39, 38, 38, 53, 65, 68, 68, 68,353		50, 38, 53, 65, 68, 68, 68, 68,354		46, 53, 65, 68, 68, 68, 68, 68,355		62, 65, 68, 68, 68, 68, 68, 68,356		68, 68, 68, 68, 68, 68, 68, 68357	},358	{/* level 1 */359		16, 11, 11, 16, 23, 27, 31, 30,360		11, 12, 12, 15, 20, 23, 23, 30,361		11, 12, 13, 16, 23, 26, 35, 47,362		16, 15, 16, 23, 26, 37, 47, 64,363		23, 20, 23, 26, 39, 51, 64, 64,364		27, 23, 26, 37, 51, 64, 64, 64,365		31, 23, 35, 47, 64, 64, 64, 64,366		30, 30, 47, 64, 64, 64, 64, 64367	},368	{/* level 2 */369		12,  8,  8, 12, 17, 21, 24, 23,370		 8,  9,  9, 11, 15, 19, 18, 23,371		 8,  9, 10, 12, 19, 20, 27, 36,372		12, 11, 12, 21, 20, 28, 36, 53,373		17, 15, 19, 20, 30, 39, 51, 59,374		21, 19, 20, 28, 39, 51, 59, 59,375		24, 18, 27, 36, 51, 59, 59, 59,376		23, 23, 36, 53, 59, 59, 59, 59377	},378	{/* level 3 - low compression quality */379		 8,  6,  6,  8, 12, 14, 16, 17,380		 6,  6,  6,  8, 10, 13, 12, 15,381		 6,  6,  7,  8, 13, 14, 18, 24,382		 8,  8,  8, 14, 13, 19, 24, 35,383		12, 10, 13, 13, 20, 26, 34, 39,384		14, 13, 14, 19, 26, 34, 39, 39,385		16, 12, 18, 24, 34, 39, 39, 39,386		17, 15, 24, 35, 39, 39, 39, 39387	}388};389 390static const unsigned char qtbl_chrominance[4][64] = {391	{/*level 0 - high compression quality */392		21, 25, 32, 38, 54, 68, 68, 68,393		25, 28, 24, 38, 54, 68, 68, 68,394		32, 24, 32, 43, 66, 68, 68, 68,395		38, 38, 43, 53, 68, 68, 68, 68,396		54, 54, 66, 68, 68, 68, 68, 68,397		68, 68, 68, 68, 68, 68, 68, 68,398		68, 68, 68, 68, 68, 68, 68, 68,399		68, 68, 68, 68, 68, 68, 68, 68400	},401	{/* level 1 */402		17, 15, 17, 21, 20, 26, 38, 48,403		15, 19, 18, 17, 20, 26, 35, 43,404		17, 18, 20, 22, 26, 30, 46, 53,405		21, 17, 22, 28, 30, 39, 53, 64,406		20, 20, 26, 30, 39, 48, 64, 64,407		26, 26, 30, 39, 48, 63, 64, 64,408		38, 35, 46, 53, 64, 64, 64, 64,409		48, 43, 53, 64, 64, 64, 64, 64410	},411	{/* level 2 */412		13, 11, 13, 16, 20, 20, 29, 37,413		11, 14, 14, 14, 16, 20, 26, 32,414		13, 14, 15, 17, 20, 23, 35, 40,415		16, 14, 17, 21, 23, 30, 40, 50,416		20, 16, 20, 23, 30, 37, 50, 59,417		20, 20, 23, 30, 37, 48, 59, 59,418		29, 26, 35, 40, 50, 59, 59, 59,419		37, 32, 40, 50, 59, 59, 59, 59420	},421	{/* level 3 - low compression quality */422		 9,  8,  9, 11, 14, 17, 19, 24,423		 8, 10,  9, 11, 14, 13, 17, 22,424		 9,  9, 13, 14, 13, 15, 23, 26,425		11, 11, 14, 14, 15, 20, 26, 33,426		14, 14, 13, 15, 20, 24, 33, 39,427		17, 13, 15, 20, 24, 32, 39, 39,428		19, 17, 23, 26, 33, 39, 39, 39,429		24, 22, 26, 33, 39, 39, 39, 39430	}431};432 433static const unsigned char hdctbl0[16] = {434	0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0435};436 437static const unsigned char hdctblg0[12] = {438	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb439};440static const unsigned char hactbl0[16] = {441	0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d442};443static const unsigned char hactblg0[162] = {444	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,445	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,446	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,447	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,448	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,449	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,450	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,451	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,452	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,453	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,454	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,455	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,456	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,457	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,458	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,459	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,460	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,461	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,462	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,463	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,464	0xf9, 0xfa465};466 467/*468 * Fourcc downgrade schema lookup tables for 422 and 420469 * chroma subsampling - fourcc on each position maps on the470 * fourcc from the table fourcc_to_dwngrd_schema_id which allows471 * to get the most suitable fourcc counterpart for the given472 * downgraded subsampling property.473 */474static const u32 subs422_fourcc_dwngrd_schema[] = {475	V4L2_PIX_FMT_NV16,476	V4L2_PIX_FMT_NV61,477};478 479static const u32 subs420_fourcc_dwngrd_schema[] = {480	V4L2_PIX_FMT_NV12,481	V4L2_PIX_FMT_NV21,482	V4L2_PIX_FMT_NV12,483	V4L2_PIX_FMT_NV21,484	V4L2_PIX_FMT_NV12,485	V4L2_PIX_FMT_NV21,486	V4L2_PIX_FMT_GREY,487	V4L2_PIX_FMT_GREY,488	V4L2_PIX_FMT_GREY,489	V4L2_PIX_FMT_GREY,490};491 492/*493 * Lookup table for translation of a fourcc to the position494 * of its downgraded counterpart in the *fourcc_dwngrd_schema495 * tables.496 */497static const u32 fourcc_to_dwngrd_schema_id[] = {498	V4L2_PIX_FMT_NV24,499	V4L2_PIX_FMT_NV42,500	V4L2_PIX_FMT_NV16,501	V4L2_PIX_FMT_NV61,502	V4L2_PIX_FMT_YUYV,503	V4L2_PIX_FMT_YVYU,504	V4L2_PIX_FMT_NV12,505	V4L2_PIX_FMT_NV21,506	V4L2_PIX_FMT_YUV420,507	V4L2_PIX_FMT_GREY,508};509 510static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)511{512	int i;513 514	for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {515		if (fourcc_to_dwngrd_schema_id[i] == fourcc)516			return i;517	}518 519	return -EINVAL;520}521 522static int s5p_jpeg_adjust_fourcc_to_subsampling(523					enum v4l2_jpeg_chroma_subsampling subs,524					u32 in_fourcc,525					u32 *out_fourcc,526					struct s5p_jpeg_ctx *ctx)527{528	int dwngrd_sch_id;529 530	if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {531		dwngrd_sch_id =532			s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);533		if (dwngrd_sch_id < 0)534			return -EINVAL;535	}536 537	switch (ctx->subsampling) {538	case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:539		*out_fourcc = V4L2_PIX_FMT_GREY;540		break;541	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:542		if (dwngrd_sch_id >543				ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)544			return -EINVAL;545		*out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];546		break;547	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:548		if (dwngrd_sch_id >549				ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)550			return -EINVAL;551		*out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];552		break;553	default:554		*out_fourcc = V4L2_PIX_FMT_GREY;555		break;556	}557 558	return 0;559}560 561static int exynos4x12_decoded_subsampling[] = {562	V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,563	V4L2_JPEG_CHROMA_SUBSAMPLING_444,564	V4L2_JPEG_CHROMA_SUBSAMPLING_422,565	V4L2_JPEG_CHROMA_SUBSAMPLING_420,566};567 568static int exynos3250_decoded_subsampling[] = {569	V4L2_JPEG_CHROMA_SUBSAMPLING_444,570	V4L2_JPEG_CHROMA_SUBSAMPLING_422,571	V4L2_JPEG_CHROMA_SUBSAMPLING_420,572	V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,573	-1,574	-1,575	V4L2_JPEG_CHROMA_SUBSAMPLING_411,576};577 578static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)579{580	return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);581}582 583static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)584{585	return container_of(fh, struct s5p_jpeg_ctx, fh);586}587 588static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)589{590	switch (ctx->jpeg->variant->version) {591	case SJPEG_S5P:592		WARN_ON(ctx->subsampling > 3);593		if (ctx->subsampling > 2)594			return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;595		return ctx->subsampling;596	case SJPEG_EXYNOS3250:597	case SJPEG_EXYNOS5420:598		WARN_ON(ctx->subsampling > 6);599		if (ctx->subsampling > 3)600			return V4L2_JPEG_CHROMA_SUBSAMPLING_411;601		return exynos3250_decoded_subsampling[ctx->subsampling];602	case SJPEG_EXYNOS4:603		WARN_ON(ctx->subsampling > 3);604		if (ctx->subsampling > 2)605			return V4L2_JPEG_CHROMA_SUBSAMPLING_420;606		return exynos4x12_decoded_subsampling[ctx->subsampling];607	case SJPEG_EXYNOS5433:608		return ctx->subsampling; /* parsed from header */609	default:610		WARN_ON(ctx->subsampling > 3);611		return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;612	}613}614 615static inline void s5p_jpeg_set_qtbl(void __iomem *regs,616				     const unsigned char *qtbl,617				     unsigned long tab, int len)618{619	int i;620 621	for (i = 0; i < len; i++)622		writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));623}624 625static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)626{627	/* this driver fills quantisation table 0 with data for luma */628	s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],629			  S5P_JPG_QTBL_CONTENT(0),630			  ARRAY_SIZE(qtbl_luminance[quality]));631}632 633static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)634{635	/* this driver fills quantisation table 1 with data for chroma */636	s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],637			  S5P_JPG_QTBL_CONTENT(1),638			  ARRAY_SIZE(qtbl_chrominance[quality]));639}640 641static inline void s5p_jpeg_set_htbl(void __iomem *regs,642				     const unsigned char *htbl,643				     unsigned long tab, int len)644{645	int i;646 647	for (i = 0; i < len; i++)648		writel((unsigned int)htbl[i], regs + tab + (i * 0x04));649}650 651static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)652{653	/* this driver fills table 0 for this component */654	s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),655						ARRAY_SIZE(hdctbl0));656}657 658static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)659{660	/* this driver fills table 0 for this component */661	s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),662						ARRAY_SIZE(hdctblg0));663}664 665static inline void s5p_jpeg_set_hactbl(void __iomem *regs)666{667	/* this driver fills table 0 for this component */668	s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),669						ARRAY_SIZE(hactbl0));670}671 672static inline void s5p_jpeg_set_hactblg(void __iomem *regs)673{674	/* this driver fills table 0 for this component */675	s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),676						ARRAY_SIZE(hactblg0));677}678 679static inline void exynos4_jpeg_set_tbl(void __iomem *regs,680					const unsigned char *tbl,681					unsigned long tab, int len)682{683	int i;684	unsigned int dword;685 686	for (i = 0; i < len; i += 4) {687		dword = tbl[i] |688			(tbl[i + 1] << 8) |689			(tbl[i + 2] << 16) |690			(tbl[i + 3] << 24);691		writel(dword, regs + tab + i);692	}693}694 695static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)696{697	/* this driver fills quantisation table 0 with data for luma */698	exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],699			     EXYNOS4_QTBL_CONTENT(0),700			     ARRAY_SIZE(qtbl_luminance[quality]));701}702 703static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)704{705	/* this driver fills quantisation table 1 with data for chroma */706	exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],707			     EXYNOS4_QTBL_CONTENT(1),708			     ARRAY_SIZE(qtbl_chrominance[quality]));709}710 711static void exynos4_jpeg_set_huff_tbl(void __iomem *base)712{713	exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,714							ARRAY_SIZE(hdctbl0));715	exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,716							ARRAY_SIZE(hdctbl0));717	exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,718							ARRAY_SIZE(hdctblg0));719	exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,720							ARRAY_SIZE(hdctblg0));721	exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,722							ARRAY_SIZE(hactbl0));723	exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,724							ARRAY_SIZE(hactbl0));725	exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,726							ARRAY_SIZE(hactblg0));727	exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,728							ARRAY_SIZE(hactblg0));729}730 731static inline int __exynos4_huff_tbl(int class, int id, bool lenval)732{733	/*734	 * class: 0 - DC, 1 - AC735	 * id: 0 - Y, 1 - Cb/Cr736	 */737	if (class) {738		if (id)739			return lenval ? EXYNOS4_HUFF_TBL_HACCL :740				EXYNOS4_HUFF_TBL_HACCV;741		return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV;742 743	}744	/* class == 0 */745	if (id)746		return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV;747 748	return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV;749}750 751static inline int exynos4_huff_tbl_len(int class, int id)752{753	return __exynos4_huff_tbl(class, id, true);754}755 756static inline int exynos4_huff_tbl_val(int class, int id)757{758	return __exynos4_huff_tbl(class, id, false);759}760 761static int get_byte(struct s5p_jpeg_buffer *buf);762static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word);763static void skip(struct s5p_jpeg_buffer *buf, long len);764 765static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)766{767	struct s5p_jpeg *jpeg = ctx->jpeg;768	struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);769	struct s5p_jpeg_buffer jpeg_buffer;770	unsigned int word;771	int c, x, components;772 773	jpeg_buffer.size = 2; /* Ls */774	jpeg_buffer.data =775		(unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sos + 2;776	jpeg_buffer.curr = 0;777 778	if (get_word_be(&jpeg_buffer, &word))779		return;780 781	if (word < 2)782		jpeg_buffer.size = 0;783	else784		jpeg_buffer.size = (long)word - 2;785 786	jpeg_buffer.data += 2;787	jpeg_buffer.curr = 0;788 789	components = get_byte(&jpeg_buffer);790	if (components == -1)791		return;792	while (components--) {793		c = get_byte(&jpeg_buffer);794		if (c == -1)795			return;796		x = get_byte(&jpeg_buffer);797		if (x == -1)798			return;799		exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c,800					(((x >> 4) & 0x1) << 1) | (x & 0x1));801	}802 803}804 805static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx)806{807	struct s5p_jpeg *jpeg = ctx->jpeg;808	struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);809	struct s5p_jpeg_buffer jpeg_buffer;810	unsigned int word;811	int c, i, n, j;812 813	for (j = 0; j < ctx->out_q.dht.n; ++j) {814		jpeg_buffer.size = ctx->out_q.dht.len[j];815		jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +816				   ctx->out_q.dht.marker[j];817		jpeg_buffer.curr = 0;818 819		word = 0;820		while (jpeg_buffer.curr < jpeg_buffer.size) {821			char id, class;822 823			c = get_byte(&jpeg_buffer);824			if (c == -1)825				return;826			id = c & 0xf;827			class = (c >> 4) & 0xf;828			n = 0;829			for (i = 0; i < 16; ++i) {830				c = get_byte(&jpeg_buffer);831				if (c == -1)832					return;833				word |= c << ((i % 4) * 8);834				if ((i + 1) % 4 == 0) {835					writel(word, jpeg->regs +836					exynos4_huff_tbl_len(class, id) +837					(i / 4) * 4);838					word = 0;839				}840				n += c;841			}842			word = 0;843			for (i = 0; i < n; ++i) {844				c = get_byte(&jpeg_buffer);845				if (c == -1)846					return;847				word |= c << ((i % 4) * 8);848				if ((i + 1) % 4 == 0) {849					writel(word, jpeg->regs +850					exynos4_huff_tbl_val(class, id) +851					(i / 4) * 4);852					word = 0;853				}854			}855			if (i % 4) {856				writel(word, jpeg->regs +857				exynos4_huff_tbl_val(class, id) + (i / 4) * 4);858			}859			word = 0;860		}861	}862}863 864static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx)865{866	struct s5p_jpeg *jpeg = ctx->jpeg;867	struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);868	struct s5p_jpeg_buffer jpeg_buffer;869	int c, x, components;870 871	jpeg_buffer.size = ctx->out_q.sof_len;872	jpeg_buffer.data =873		(unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sof;874	jpeg_buffer.curr = 0;875 876	skip(&jpeg_buffer, 5); /* P, Y, X */877	components = get_byte(&jpeg_buffer);878	if (components == -1)879		return;880 881	exynos4_jpeg_set_dec_components(jpeg->regs, components);882 883	while (components--) {884		c = get_byte(&jpeg_buffer);885		if (c == -1)886			return;887		skip(&jpeg_buffer, 1);888		x = get_byte(&jpeg_buffer);889		if (x == -1)890			return;891		exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x);892	}893}894 895static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx)896{897	struct s5p_jpeg *jpeg = ctx->jpeg;898	struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);899	struct s5p_jpeg_buffer jpeg_buffer;900	unsigned int word;901	int c, i, j;902 903	for (j = 0; j < ctx->out_q.dqt.n; ++j) {904		jpeg_buffer.size = ctx->out_q.dqt.len[j];905		jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +906				   ctx->out_q.dqt.marker[j];907		jpeg_buffer.curr = 0;908 909		word = 0;910		while (jpeg_buffer.size - jpeg_buffer.curr >= 65) {911			char id;912 913			c = get_byte(&jpeg_buffer);914			if (c == -1)915				return;916			id = c & 0xf;917			/* nonzero means extended mode - not supported */918			if ((c >> 4) & 0xf)919				return;920			for (i = 0; i < 64; ++i) {921				c = get_byte(&jpeg_buffer);922				if (c == -1)923					return;924				word |= c << ((i % 4) * 8);925				if ((i + 1) % 4 == 0) {926					writel(word, jpeg->regs +927					EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4);928					word = 0;929				}930			}931			word = 0;932		}933	}934}935 936/*937 * ============================================================================938 * Device file operations939 * ============================================================================940 */941 942static int queue_init(void *priv, struct vb2_queue *src_vq,943		      struct vb2_queue *dst_vq);944static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,945				__u32 pixelformat, unsigned int fmt_type);946static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);947 948static int s5p_jpeg_open(struct file *file)949{950	struct s5p_jpeg *jpeg = video_drvdata(file);951	struct video_device *vfd = video_devdata(file);952	struct s5p_jpeg_ctx *ctx;953	struct s5p_jpeg_fmt *out_fmt, *cap_fmt;954	int ret = 0;955 956	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);957	if (!ctx)958		return -ENOMEM;959 960	if (mutex_lock_interruptible(&jpeg->lock)) {961		ret = -ERESTARTSYS;962		goto free;963	}964 965	v4l2_fh_init(&ctx->fh, vfd);966	/* Use separate control handler per file handle */967	ctx->fh.ctrl_handler = &ctx->ctrl_handler;968	file->private_data = &ctx->fh;969	v4l2_fh_add(&ctx->fh);970 971	ctx->jpeg = jpeg;972	if (vfd == jpeg->vfd_encoder) {973		ctx->mode = S5P_JPEG_ENCODE;974		out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,975							FMT_TYPE_OUTPUT);976		cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,977							FMT_TYPE_CAPTURE);978	} else {979		ctx->mode = S5P_JPEG_DECODE;980		out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,981							FMT_TYPE_OUTPUT);982		cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,983							FMT_TYPE_CAPTURE);984		ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;985	}986 987	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);988	if (IS_ERR(ctx->fh.m2m_ctx)) {989		ret = PTR_ERR(ctx->fh.m2m_ctx);990		goto error;991	}992 993	ctx->out_q.fmt = out_fmt;994	ctx->cap_q.fmt = cap_fmt;995 996	ret = s5p_jpeg_controls_create(ctx);997	if (ret < 0)998		goto error;999 1000	mutex_unlock(&jpeg->lock);1001	return 0;1002 1003error:1004	v4l2_fh_del(&ctx->fh);1005	v4l2_fh_exit(&ctx->fh);1006	mutex_unlock(&jpeg->lock);1007free:1008	kfree(ctx);1009	return ret;1010}1011 1012static int s5p_jpeg_release(struct file *file)1013{1014	struct s5p_jpeg *jpeg = video_drvdata(file);1015	struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);1016 1017	mutex_lock(&jpeg->lock);1018	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);1019	v4l2_ctrl_handler_free(&ctx->ctrl_handler);1020	v4l2_fh_del(&ctx->fh);1021	v4l2_fh_exit(&ctx->fh);1022	kfree(ctx);1023	mutex_unlock(&jpeg->lock);1024 1025	return 0;1026}1027 1028static const struct v4l2_file_operations s5p_jpeg_fops = {1029	.owner		= THIS_MODULE,1030	.open		= s5p_jpeg_open,1031	.release	= s5p_jpeg_release,1032	.poll		= v4l2_m2m_fop_poll,1033	.unlocked_ioctl	= video_ioctl2,1034	.mmap		= v4l2_m2m_fop_mmap,1035};1036 1037/*1038 * ============================================================================1039 * video ioctl operations1040 * ============================================================================1041 */1042 1043static int get_byte(struct s5p_jpeg_buffer *buf)1044{1045	if (buf->curr >= buf->size)1046		return -1;1047 1048	return ((unsigned char *)buf->data)[buf->curr++];1049}1050 1051static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)1052{1053	unsigned int temp;1054	int byte;1055 1056	byte = get_byte(buf);1057	if (byte == -1)1058		return -1;1059	temp = byte << 8;1060	byte = get_byte(buf);1061	if (byte == -1)1062		return -1;1063	*word = (unsigned int)byte | temp;1064 1065	return 0;1066}1067 1068static void skip(struct s5p_jpeg_buffer *buf, long len)1069{1070	if (len <= 0)1071		return;1072 1073	while (len--)1074		get_byte(buf);1075}1076 1077static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx,1078					unsigned int subsampling)1079{1080	unsigned int version;1081 1082	switch (subsampling) {1083	case 0x11:1084		ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;1085		break;1086	case 0x21:1087		ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;1088		break;1089	case 0x22:1090		ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;1091		break;1092	case 0x33:1093		ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;1094		break;1095	case 0x41:1096		/*1097		 * 4:1:1 subsampling only supported by 3250, 5420, and 54331098		 * variants1099		 */1100		version = ctx->jpeg->variant->version;1101		if (version != SJPEG_EXYNOS3250 &&1102		    version != SJPEG_EXYNOS5420 &&1103		    version != SJPEG_EXYNOS5433)1104			return false;1105 1106		ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411;1107		break;1108	default:1109		return false;1110	}1111 1112	return true;1113}1114 1115static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,1116			       unsigned long buffer, unsigned long size,1117			       struct s5p_jpeg_ctx *ctx)1118{1119	int c, components = 0, notfound, n_dht = 0, n_dqt = 0;1120	unsigned int height = 0, width = 0, word, subsampling = 0;1121	unsigned int sos = 0, sof = 0, sof_len = 0;1122	unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER];1123	unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];1124	long length;1125	struct s5p_jpeg_buffer jpeg_buffer;1126 1127	jpeg_buffer.size = size;1128	jpeg_buffer.data = buffer;1129	jpeg_buffer.curr = 0;1130 1131	notfound = 1;1132	while (notfound || !sos) {1133		c = get_byte(&jpeg_buffer);1134		if (c == -1)1135			return false;1136		if (c != 0xff)1137			continue;1138		do1139			c = get_byte(&jpeg_buffer);1140		while (c == 0xff);1141		if (c == -1)1142			return false;1143		if (c == 0)1144			continue;1145		length = 0;1146		switch (c) {1147		/* JPEG_MARKER_SOF0: baseline JPEG */1148		case JPEG_MARKER_SOF0:1149			if (get_word_be(&jpeg_buffer, &word))1150				break;1151			length = (long)word - 2;1152			if (length <= 0)1153				return false;1154			sof = jpeg_buffer.curr; /* after 0xffc0 */1155			sof_len = length;1156			if (get_byte(&jpeg_buffer) == -1)1157				break;1158			if (get_word_be(&jpeg_buffer, &height))1159				break;1160			if (get_word_be(&jpeg_buffer, &width))1161				break;1162			components = get_byte(&jpeg_buffer);1163			if (components == -1)1164				break;1165 1166			if (components == 1) {1167				subsampling = 0x33;1168			} else {1169				skip(&jpeg_buffer, 1);1170				subsampling = get_byte(&jpeg_buffer);1171				skip(&jpeg_buffer, 1);1172			}1173			if (components > 3)1174				return false;1175			skip(&jpeg_buffer, components * 2);1176			notfound = 0;1177			break;1178 1179		case JPEG_MARKER_DQT:1180			if (get_word_be(&jpeg_buffer, &word))1181				break;1182			length = (long)word - 2;1183			if (length <= 0)1184				return false;1185			if (n_dqt >= S5P_JPEG_MAX_MARKER)1186				return false;1187			dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */1188			dqt_len[n_dqt++] = length;1189			skip(&jpeg_buffer, length);1190			break;1191 1192		case JPEG_MARKER_DHT:1193			if (get_word_be(&jpeg_buffer, &word))1194				break;1195			length = (long)word - 2;1196			if (length <= 0)1197				return false;1198			if (n_dht >= S5P_JPEG_MAX_MARKER)1199				return false;1200			dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */1201			dht_len[n_dht++] = length;1202			skip(&jpeg_buffer, length);1203			break;1204 1205		case JPEG_MARKER_SOS:1206			sos = jpeg_buffer.curr - 2; /* 0xffda */1207			break;1208 1209		/* skip payload-less markers */1210		case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7:1211		case JPEG_MARKER_SOI:1212		case JPEG_MARKER_EOI:1213		case JPEG_MARKER_TEM:1214			break;1215 1216		/* skip uninteresting payload markers */1217		default:1218			if (get_word_be(&jpeg_buffer, &word))1219				break;1220			length = (long)word - 2;1221			/* No need to check underflows as skip() does it  */1222			skip(&jpeg_buffer, length);1223			break;1224		}1225	}1226 1227	if (notfound || !sos || !s5p_jpeg_subsampling_decode(ctx, subsampling))1228		return false;1229 1230	result->w = width;1231	result->h = height;1232	result->sos = sos;1233	result->dht.n = n_dht;1234	while (n_dht--) {1235		result->dht.marker[n_dht] = dht[n_dht];1236		result->dht.len[n_dht] = dht_len[n_dht];1237	}1238	result->dqt.n = n_dqt;1239	while (n_dqt--) {1240		result->dqt.marker[n_dqt] = dqt[n_dqt];1241		result->dqt.len[n_dqt] = dqt_len[n_dqt];1242	}1243	result->sof = sof;1244	result->sof_len = sof_len;1245 1246	return true;1247}1248 1249static int s5p_jpeg_querycap(struct file *file, void *priv,1250			   struct v4l2_capability *cap)1251{1252	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);1253 1254	if (ctx->mode == S5P_JPEG_ENCODE) {1255		strscpy(cap->driver, S5P_JPEG_M2M_NAME,1256			sizeof(cap->driver));1257		strscpy(cap->card, S5P_JPEG_M2M_NAME " encoder",1258			sizeof(cap->card));1259	} else {1260		strscpy(cap->driver, S5P_JPEG_M2M_NAME,1261			sizeof(cap->driver));1262		strscpy(cap->card, S5P_JPEG_M2M_NAME " decoder",1263			sizeof(cap->card));1264	}1265	return 0;1266}1267 1268static int enum_fmt(struct s5p_jpeg_ctx *ctx,1269		    struct s5p_jpeg_fmt *sjpeg_formats, int n,1270		    struct v4l2_fmtdesc *f, u32 type)1271{1272	int i, num = 0;1273	unsigned int fmt_ver_flag = ctx->jpeg->variant->fmt_ver_flag;1274 1275	for (i = 0; i < n; ++i) {1276		if (sjpeg_formats[i].flags & type &&1277		    sjpeg_formats[i].flags & fmt_ver_flag) {1278			/* index-th format of type type found ? */1279			if (num == f->index)1280				break;1281			/* Correct type but haven't reached our index yet,1282			 * just increment per-type index1283			 */1284			++num;1285		}1286	}1287 1288	/* Format not found */1289	if (i >= n)1290		return -EINVAL;1291 1292	f->pixelformat = sjpeg_formats[i].fourcc;1293 1294	return 0;1295}1296 1297static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,1298				   struct v4l2_fmtdesc *f)1299{1300	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);1301 1302	if (ctx->mode == S5P_JPEG_ENCODE)1303		return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,1304				SJPEG_FMT_FLAG_ENC_CAPTURE);1305 1306	return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,1307			SJPEG_FMT_FLAG_DEC_CAPTURE);1308}1309 1310static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,1311				   struct v4l2_fmtdesc *f)1312{1313	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);1314 1315	if (ctx->mode == S5P_JPEG_ENCODE)1316		return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,1317				SJPEG_FMT_FLAG_ENC_OUTPUT);1318 1319	return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,1320			SJPEG_FMT_FLAG_DEC_OUTPUT);1321}1322 1323static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,1324					  enum v4l2_buf_type type)1325{1326	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)1327		return &ctx->out_q;1328	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)1329		return &ctx->cap_q;1330 1331	return NULL;1332}1333 1334static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)1335{1336	struct vb2_queue *vq;1337	struct s5p_jpeg_q_data *q_data = NULL;1338	struct v4l2_pix_format *pix = &f->fmt.pix;1339	struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);1340 1341	vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);1342	if (!vq)1343		return -EINVAL;1344 1345	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&1346	    ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)1347		return -EINVAL;1348	q_data = get_q_data(ct, f->type);1349	BUG_ON(q_data == NULL);1350 1351	pix->width = q_data->w;1352	pix->height = q_data->h;1353	pix->field = V4L2_FIELD_NONE;1354	pix->pixelformat = q_data->fmt->fourcc;1355	pix->bytesperline = 0;1356	if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {1357		u32 bpl = q_data->w;1358 1359		if (q_data->fmt->colplanes == 1)1360			bpl = (bpl * q_data->fmt->depth) >> 3;1361		pix->bytesperline = bpl;1362	}1363	pix->sizeimage = q_data->size;1364 1365	return 0;1366}1367 1368static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,1369				u32 pixelformat, unsigned int fmt_type)1370{1371	unsigned int k, fmt_flag;1372 1373	if (ctx->mode == S5P_JPEG_ENCODE)1374		fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?1375				SJPEG_FMT_FLAG_ENC_OUTPUT :1376				SJPEG_FMT_FLAG_ENC_CAPTURE;1377	else1378		fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?1379				SJPEG_FMT_FLAG_DEC_OUTPUT :1380				SJPEG_FMT_FLAG_DEC_CAPTURE;1381 1382	for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {1383		struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];1384 1385		if (fmt->fourcc == pixelformat &&1386		    fmt->flags & fmt_flag &&1387		    fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {1388			return fmt;1389		}1390	}1391 1392	return NULL;1393}1394 1395static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,1396				   u32 *w, unsigned int wmin, unsigned int wmax,1397				   unsigned int walign,1398				   u32 *h, unsigned int hmin, unsigned int hmax,1399				   unsigned int halign)1400{1401	int width, height, w_step, h_step;1402 1403	width = *w;1404	height = *h;1405 1406	w_step = 1 << walign;1407	h_step = 1 << halign;1408 1409	if (ctx->jpeg->variant->hw3250_compat) {1410		/*1411		 * Rightmost and bottommost pixels are cropped by the1412		 * Exynos3250/compatible JPEG IP for RGB formats, for the1413		 * specific width and height values respectively. This1414		 * assignment will result in v4l_bound_align_image returning1415		 * dimensions reduced by 1 for the aforementioned cases.1416		 */1417		if (w_step == 4 && ((width & 3) == 1)) {1418			wmax = width;1419			hmax = height;1420		}1421	}1422 1423	v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);1424 1425	if (*w < width && (*w + w_step) < wmax)1426		*w += w_step;1427	if (*h < height && (*h + h_step) < hmax)1428		*h += h_step;1429}1430 1431static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,1432			  struct s5p_jpeg_ctx *ctx, int q_type)1433{1434	struct v4l2_pix_format *pix = &f->fmt.pix;1435 1436	if (pix->field == V4L2_FIELD_ANY)1437		pix->field = V4L2_FIELD_NONE;1438	else if (pix->field != V4L2_FIELD_NONE)1439		return -EINVAL;1440 1441	/* V4L2 specification suggests the driver corrects the format struct1442	 * if any of the dimensions is unsupported1443	 */1444	if (q_type == FMT_TYPE_OUTPUT)1445		jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,1446				       S5P_JPEG_MAX_WIDTH, 0,1447				       &pix->height, S5P_JPEG_MIN_HEIGHT,1448				       S5P_JPEG_MAX_HEIGHT, 0);1449	else1450		jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,1451				       S5P_JPEG_MAX_WIDTH, fmt->h_align,1452				       &pix->height, S5P_JPEG_MIN_HEIGHT,1453				       S5P_JPEG_MAX_HEIGHT, fmt->v_align);1454 1455	if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {1456		if (pix->sizeimage <= 0)1457			pix->sizeimage = PAGE_SIZE;1458		pix->bytesperline = 0;1459	} else {1460		u32 bpl = pix->bytesperline;1461 1462		if (fmt->colplanes > 1 && bpl < pix->width)1463			bpl = pix->width; /* planar */1464 1465		if (fmt->colplanes == 1 && /* packed */1466		    (bpl << 3) / fmt->depth < pix->width)1467			bpl = (pix->width * fmt->depth) >> 3;1468 1469		pix->bytesperline = bpl;1470		pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;1471	}1472 1473	return 0;1474}1475 1476static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,1477				  struct v4l2_format *f)1478{1479	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);1480	struct v4l2_pix_format *pix = &f->fmt.pix;1481	struct s5p_jpeg_fmt *fmt;1482	int ret;1483 1484	fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,1485						FMT_TYPE_CAPTURE);1486	if (!fmt) {1487		v4l2_err(&ctx->jpeg->v4l2_dev,1488			 "Fourcc format (0x%08x) invalid.\n",1489			 f->fmt.pix.pixelformat);1490		return -EINVAL;1491	}1492 1493	if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE)1494		goto exit;1495 1496	/*1497	 * The exynos4x12 device requires resulting YUV image1498	 * subsampling not to be lower than the input jpeg subsampling.1499	 * If this requirement is not met then downgrade the requested1500	 * capture format to the one with subsampling equal to the input jpeg.1501	 */1502	if ((fmt->flags & SJPEG_FMT_NON_RGB) &&1503	    (fmt->subsampling < ctx->subsampling)) {1504		ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,1505							    fmt->fourcc,1506							    &pix->pixelformat,1507							    ctx);1508		if (ret < 0)1509			pix->pixelformat = V4L2_PIX_FMT_GREY;1510 1511		fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,1512							FMT_TYPE_CAPTURE);1513	}1514 1515	/*1516	 * Decompression of a JPEG file with 4:2:0 subsampling and odd1517	 * width to the YUV 4:2:0 compliant formats produces a raw image1518	 * with broken luma component. Adjust capture format to RGB5651519	 * in such a case.1520	 */1521	if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&1522	    (ctx->out_q.w & 1) &&1523	    (pix->pixelformat == V4L2_PIX_FMT_NV12 ||1524	     pix->pixelformat == V4L2_PIX_FMT_NV21 ||1525	     pix->pixelformat == V4L2_PIX_FMT_YUV420)) {1526		pix->pixelformat = V4L2_PIX_FMT_RGB565;1527		fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,1528							FMT_TYPE_CAPTURE);1529	}1530 1531exit:1532	return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);1533}1534 1535static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,1536				  struct v4l2_format *f)1537{1538	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);1539	struct s5p_jpeg_fmt *fmt;1540 1541	fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,1542						FMT_TYPE_OUTPUT);1543	if (!fmt) {1544		v4l2_err(&ctx->jpeg->v4l2_dev,1545			 "Fourcc format (0x%08x) invalid.\n",1546			 f->fmt.pix.pixelformat);1547		return -EINVAL;1548	}1549 1550	return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);1551}1552 1553static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,1554						struct v4l2_format *f,1555						int fmt_depth)1556{1557	struct v4l2_pix_format *pix = &f->fmt.pix;1558	u32 pix_fmt = f->fmt.pix.pixelformat;1559	int w = pix->width, h = pix->height, wh_align;1560	int padding = 0;1561 1562	if (pix_fmt == V4L2_PIX_FMT_RGB32 ||1563	    pix_fmt == V4L2_PIX_FMT_RGB565 ||1564	    pix_fmt == V4L2_PIX_FMT_NV24 ||1565	    pix_fmt == V4L2_PIX_FMT_NV42 ||1566	    pix_fmt == V4L2_PIX_FMT_NV12 ||1567	    pix_fmt == V4L2_PIX_FMT_NV21 ||1568	    pix_fmt == V4L2_PIX_FMT_YUV420)1569		wh_align = 4;1570	else1571		wh_align = 1;1572 1573	jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,1574			       S5P_JPEG_MAX_WIDTH, wh_align,1575			       &h, S5P_JPEG_MIN_HEIGHT,1576			       S5P_JPEG_MAX_HEIGHT, wh_align);1577 1578	if (ctx->jpeg->variant->version == SJPEG_EXYNOS4)1579		padding = PAGE_SIZE;1580 1581	return (w * h * fmt_depth >> 3) + padding;1582}1583 1584static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,1585				   struct v4l2_rect *r);1586 1587static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)1588{1589	struct vb2_queue *vq;1590	struct s5p_jpeg_q_data *q_data = NULL;1591	struct v4l2_pix_format *pix = &f->fmt.pix;1592	struct v4l2_ctrl *ctrl_subs;1593	struct v4l2_rect scale_rect;1594	unsigned int f_type;1595 1596	vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);1597	if (!vq)1598		return -EINVAL;1599 1600	q_data = get_q_data(ct, f->type);1601	BUG_ON(q_data == NULL);1602 1603	if (vb2_is_busy(vq)) {1604		v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);1605		return -EBUSY;1606	}1607 1608	f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?1609			FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;1610 1611	q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);1612	if (ct->mode == S5P_JPEG_ENCODE ||1613		(ct->mode == S5P_JPEG_DECODE &&1614		q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)) {1615		q_data->w = pix->width;1616		q_data->h = pix->height;1617	}1618	if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {1619		/*1620		 * During encoding Exynos4x12 SoCs access wider memory area1621		 * than it results from Image_x and Image_y values written to1622		 * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu1623		 * page fault calculate proper buffer size in such a case.1624		 */1625		if (ct->jpeg->variant->hw_ex4_compat &&1626		    f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)1627			q_data->size = exynos4_jpeg_get_output_buffer_size(ct,1628							f,1629							q_data->fmt->depth);1630		else1631			q_data->size = q_data->w * q_data->h *1632						q_data->fmt->depth >> 3;1633	} else {1634		q_data->size = pix->sizeimage;1635	}1636 1637	if (f_type == FMT_TYPE_OUTPUT) {1638		ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,1639					V4L2_CID_JPEG_CHROMA_SUBSAMPLING);1640		if (ctrl_subs)1641			v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);1642		ct->crop_altered = false;1643	}1644 1645	/*1646	 * For decoding init crop_rect with capture buffer dimmensions which1647	 * contain aligned dimensions of the input JPEG image and do it only1648	 * if crop rectangle hasn't been altered by the user space e.g. with1649	 * S_SELECTION ioctl. For encoding assign output buffer dimensions.1650	 */1651	if (!ct->crop_altered &&1652	    ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||1653	     (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {1654		ct->crop_rect.width = pix->width;1655		ct->crop_rect.height = pix->height;1656	}1657 1658	/*1659	 * Prevent downscaling to YUV420 format by more than 21660	 * for Exynos3250/compatible SoC as it produces broken raw image1661	 * in such cases.1662	 */1663	if (ct->mode == S5P_JPEG_DECODE &&1664	    f_type == FMT_TYPE_CAPTURE &&1665	    ct->jpeg->variant->hw3250_compat &&1666	    pix->pixelformat == V4L2_PIX_FMT_YUV420 &&1667	    ct->scale_factor > 2) {1668		scale_rect.width = ct->out_q.w / 2;1669		scale_rect.height = ct->out_q.h / 2;1670		exynos3250_jpeg_try_downscale(ct, &scale_rect);1671	}1672 1673	return 0;1674}1675 1676static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,1677				struct v4l2_format *f)1678{1679	int ret;1680 1681	ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);1682	if (ret)1683		return ret;1684 1685	return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);1686}1687 1688static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,1689				struct v4l2_format *f)1690{1691	int ret;1692 1693	ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);1694	if (ret)1695		return ret;1696 1697	return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);1698}1699 1700static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh,1701				    const struct v4l2_event_subscription *sub)1702{1703	if (sub->type == V4L2_EVENT_SOURCE_CHANGE)1704		return v4l2_src_change_event_subscribe(fh, sub);1705 1706	return -EINVAL;1707}1708 1709static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,1710				   struct v4l2_rect *r)1711{1712	int w_ratio, h_ratio, scale_factor, cur_ratio, i;1713 1714	w_ratio = ctx->out_q.w / r->width;1715	h_ratio = ctx->out_q.h / r->height;1716 1717	scale_factor = max(w_ratio, h_ratio);1718	scale_factor = clamp_val(scale_factor, 1, 8);1719 1720	/* Align scale ratio to the nearest power of 2 */1721	for (i = 0; i <= 3; ++i) {1722		cur_ratio = 1 << i;1723		if (scale_factor <= cur_ratio) {1724			ctx->scale_factor = cur_ratio;1725			break;1726		}1727	}1728 1729	r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);1730	r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);1731 1732	ctx->crop_rect.width = r->width;1733	ctx->crop_rect.height = r->height;1734	ctx->crop_rect.left = 0;1735	ctx->crop_rect.top = 0;1736 1737	ctx->crop_altered = true;1738 1739	return 0;1740}1741 1742static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,1743				   struct v4l2_rect *r)1744{1745	struct v4l2_rect base_rect;1746	int w_step, h_step;1747 1748	switch (ctx->cap_q.fmt->fourcc) {1749	case V4L2_PIX_FMT_NV12:1750	case V4L2_PIX_FMT_NV21:1751		w_step = 1;1752		h_step = 2;1753		break;1754	case V4L2_PIX_FMT_YUV420:1755		w_step = 2;1756		h_step = 2;1757		break;1758	default:1759		w_step = 1;1760		h_step = 1;1761		break;1762	}1763 1764	base_rect.top = 0;1765	base_rect.left = 0;1766	base_rect.width = ctx->out_q.w;1767	base_rect.height = ctx->out_q.h;1768 1769	r->width = round_down(r->width, w_step);1770	r->height = round_down(r->height, h_step);1771	r->left = round_down(r->left, 2);1772	r->top = round_down(r->top, 2);1773 1774	if (!v4l2_rect_enclosed(r, &base_rect))1775		return -EINVAL;1776 1777	ctx->crop_rect.left = r->left;1778	ctx->crop_rect.top = r->top;1779	ctx->crop_rect.width = r->width;1780	ctx->crop_rect.height = r->height;1781 1782	ctx->crop_altered = true;1783 1784	return 0;1785}1786 1787/*1788 * V4L2 controls1789 */1790 1791static int s5p_jpeg_g_selection(struct file *file, void *priv,1792			 struct v4l2_selection *s)1793{1794	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);1795 1796	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&1797	    s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1798		return -EINVAL;1799 1800	/* For JPEG blob active == default == bounds */1801	switch (s->target) {1802	case V4L2_SEL_TGT_CROP:1803	case V4L2_SEL_TGT_CROP_BOUNDS:1804	case V4L2_SEL_TGT_CROP_DEFAULT:1805	case V4L2_SEL_TGT_COMPOSE_DEFAULT:1806		s->r.width = ctx->out_q.w;1807		s->r.height = ctx->out_q.h;1808		s->r.left = 0;1809		s->r.top = 0;1810		break;1811	case V4L2_SEL_TGT_COMPOSE:1812	case V4L2_SEL_TGT_COMPOSE_BOUNDS:1813	case V4L2_SEL_TGT_COMPOSE_PADDED:1814		s->r.width = ctx->crop_rect.width;1815		s->r.height =  ctx->crop_rect.height;1816		s->r.left = ctx->crop_rect.left;1817		s->r.top = ctx->crop_rect.top;1818		break;1819	default:1820		return -EINVAL;1821	}1822	return 0;1823}1824 1825/*1826 * V4L2 controls1827 */1828static int s5p_jpeg_s_selection(struct file *file, void *fh,1829				  struct v4l2_selection *s)1830{1831	struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);1832	struct v4l2_rect *rect = &s->r;1833	int ret = -EINVAL;1834 1835	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)1836		return -EINVAL;1837 1838	if (s->target == V4L2_SEL_TGT_COMPOSE) {1839		if (ctx->mode != S5P_JPEG_DECODE)1840			return -EINVAL;1841		if (ctx->jpeg->variant->hw3250_compat)1842			ret = exynos3250_jpeg_try_downscale(ctx, rect);1843	} else if (s->target == V4L2_SEL_TGT_CROP) {1844		if (ctx->mode != S5P_JPEG_ENCODE)1845			return -EINVAL;1846		if (ctx->jpeg->variant->hw3250_compat)1847			ret = exynos3250_jpeg_try_crop(ctx, rect);1848	}1849 1850	return ret;1851}1852 1853static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)1854{1855	struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);1856	struct s5p_jpeg *jpeg = ctx->jpeg;1857	unsigned long flags;1858 1859	switch (ctrl->id) {1860	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:1861		spin_lock_irqsave(&jpeg->slock, flags);1862		ctrl->val = s5p_jpeg_to_user_subsampling(ctx);1863		spin_unlock_irqrestore(&jpeg->slock, flags);1864		break;1865	}1866 1867	return 0;1868}1869 1870static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)1871{1872	switch (ctx->jpeg->variant->version) {1873	case SJPEG_S5P:1874		return 0;1875	case SJPEG_EXYNOS3250:1876	case SJPEG_EXYNOS5420:1877		/*1878		 * The exynos3250/compatible device can produce JPEG image only1879		 * of 4:4:4 subsampling when given RGB32 source image.1880		 */1881		if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)1882			*ctrl_val = 0;1883		break;1884	case SJPEG_EXYNOS4:1885		/*1886		 * The exynos4x12 device requires input raw image fourcc1887		 * to be V4L2_PIX_FMT_GREY if gray jpeg format1888		 * is to be set.1889		 */1890		if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&1891		    *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)1892			return -EINVAL;1893		break;1894	}1895 1896	/*1897	 * The exynos4x12 and exynos3250/compatible devices require resulting1898	 * jpeg subsampling not to be lower than the input raw image1899	 * subsampling.1900	 */1901	if (ctx->out_q.fmt->subsampling > *ctrl_val)1902		*ctrl_val = ctx->out_q.fmt->subsampling;1903 1904	return 0;1905}1906 1907static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)1908{1909	struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);1910	unsigned long flags;1911	int ret = 0;1912 1913	spin_lock_irqsave(&ctx->jpeg->slock, flags);1914 1915	if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)1916		ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);1917 1918	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);1919	return ret;1920}1921 1922static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)1923{1924	struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);1925	unsigned long flags;1926 1927	spin_lock_irqsave(&ctx->jpeg->slock, flags);1928 1929	switch (ctrl->id) {1930	case V4L2_CID_JPEG_COMPRESSION_QUALITY:1931		ctx->compr_quality = ctrl->val;1932		break;1933	case V4L2_CID_JPEG_RESTART_INTERVAL:1934		ctx->restart_interval = ctrl->val;1935		break;1936	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:1937		ctx->subsampling = ctrl->val;1938		break;1939	}1940 1941	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);1942	return 0;1943}1944 1945static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {1946	.g_volatile_ctrl	= s5p_jpeg_g_volatile_ctrl,1947	.try_ctrl		= s5p_jpeg_try_ctrl,1948	.s_ctrl			= s5p_jpeg_s_ctrl,1949};1950 1951static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)1952{1953	unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */1954	struct v4l2_ctrl *ctrl;1955	int ret;1956 1957	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);1958 1959	if (ctx->mode == S5P_JPEG_ENCODE) {1960		v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,1961				  V4L2_CID_JPEG_COMPRESSION_QUALITY,1962				  0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);1963 1964		v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,1965				  V4L2_CID_JPEG_RESTART_INTERVAL,1966				  0, 0xffff, 1, 0);1967		if (ctx->jpeg->variant->version == SJPEG_S5P)1968			mask = ~0x06; /* 422, 420 */1969	}1970 1971	ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,1972				      V4L2_CID_JPEG_CHROMA_SUBSAMPLING,1973				      V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,1974				      V4L2_JPEG_CHROMA_SUBSAMPLING_422);1975 1976	if (ctx->ctrl_handler.error) {1977		ret = ctx->ctrl_handler.error;1978		goto error_free;1979	}1980 1981	if (ctx->mode == S5P_JPEG_DECODE)1982		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |1983			V4L2_CTRL_FLAG_READ_ONLY;1984 1985	ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);1986	if (ret < 0)1987		goto error_free;1988 1989	return ret;1990 1991error_free:1992	v4l2_ctrl_handler_free(&ctx->ctrl_handler);1993	return ret;1994}1995 1996static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {1997	.vidioc_querycap		= s5p_jpeg_querycap,1998 1999	.vidioc_enum_fmt_vid_cap	= s5p_jpeg_enum_fmt_vid_cap,2000	.vidioc_enum_fmt_vid_out	= s5p_jpeg_enum_fmt_vid_out,2001 2002	.vidioc_g_fmt_vid_cap		= s5p_jpeg_g_fmt,2003	.vidioc_g_fmt_vid_out		= s5p_jpeg_g_fmt,2004 2005	.vidioc_try_fmt_vid_cap		= s5p_jpeg_try_fmt_vid_cap,2006	.vidioc_try_fmt_vid_out		= s5p_jpeg_try_fmt_vid_out,2007 2008	.vidioc_s_fmt_vid_cap		= s5p_jpeg_s_fmt_vid_cap,2009	.vidioc_s_fmt_vid_out		= s5p_jpeg_s_fmt_vid_out,2010 2011	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,2012	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,2013	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,2014	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,2015 2016	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,2017	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,2018 2019	.vidioc_g_selection		= s5p_jpeg_g_selection,2020	.vidioc_s_selection		= s5p_jpeg_s_selection,2021 2022	.vidioc_subscribe_event		= s5p_jpeg_subscribe_event,2023	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,2024};2025 2026/*2027 * ============================================================================2028 * mem2mem callbacks2029 * ============================================================================2030 */2031 2032static void s5p_jpeg_device_run(void *priv)2033{2034	struct s5p_jpeg_ctx *ctx = priv;2035	struct s5p_jpeg *jpeg = ctx->jpeg;2036	struct vb2_v4l2_buffer *src_buf, *dst_buf;2037	unsigned long src_addr, dst_addr, flags;2038 2039	spin_lock_irqsave(&ctx->jpeg->slock, flags);2040 2041	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);2042	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);2043	src_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);2044	dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);2045 2046	s5p_jpeg_reset(jpeg->regs);2047	s5p_jpeg_poweron(jpeg->regs);2048	s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);2049	if (ctx->mode == S5P_JPEG_ENCODE) {2050		if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)2051			s5p_jpeg_input_raw_mode(jpeg->regs,2052							S5P_JPEG_RAW_IN_565);2053		else2054			s5p_jpeg_input_raw_mode(jpeg->regs,2055							S5P_JPEG_RAW_IN_422);2056		s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);2057		s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);2058		s5p_jpeg_x(jpeg->regs, ctx->out_q.w);2059		s5p_jpeg_y(jpeg->regs, ctx->out_q.h);2060		s5p_jpeg_imgadr(jpeg->regs, src_addr);2061		s5p_jpeg_jpgadr(jpeg->regs, dst_addr);2062 2063		/* ultimately comes from sizeimage from userspace */2064		s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);2065 2066		/* JPEG RGB to YCbCr conversion matrix */2067		s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);2068		s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);2069		s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);2070		s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);2071		s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);2072		s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);2073		s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);2074		s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);2075		s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);2076 2077		/*2078		 * JPEG IP allows storing 4 quantization tables2079		 * We fill table 0 for luma and table 1 for chroma2080		 */2081		s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);2082		s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);2083		/* use table 0 for Y */2084		s5p_jpeg_qtbl(jpeg->regs, 1, 0);2085		/* use table 1 for Cb and Cr*/2086		s5p_jpeg_qtbl(jpeg->regs, 2, 1);2087		s5p_jpeg_qtbl(jpeg->regs, 3, 1);2088 2089		/* Y, Cb, Cr use Huffman table 0 */2090		s5p_jpeg_htbl_ac(jpeg->regs, 1);2091		s5p_jpeg_htbl_dc(jpeg->regs, 1);2092		s5p_jpeg_htbl_ac(jpeg->regs, 2);2093		s5p_jpeg_htbl_dc(jpeg->regs, 2);2094		s5p_jpeg_htbl_ac(jpeg->regs, 3);2095		s5p_jpeg_htbl_dc(jpeg->regs, 3);2096	} else { /* S5P_JPEG_DECODE */2097		s5p_jpeg_rst_int_enable(jpeg->regs, true);2098		s5p_jpeg_data_num_int_enable(jpeg->regs, true);2099		s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);2100		if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)2101			s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);2102		else2103			s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);2104		s5p_jpeg_jpgadr(jpeg->regs, src_addr);2105		s5p_jpeg_imgadr(jpeg->regs, dst_addr);2106	}2107 2108	s5p_jpeg_start(jpeg->regs);2109 2110	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);2111}2112 2113static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)2114{2115	struct s5p_jpeg *jpeg = ctx->jpeg;2116	struct s5p_jpeg_fmt *fmt;2117	struct vb2_v4l2_buffer *vb;2118	struct s5p_jpeg_addr jpeg_addr = {};2119	u32 pix_size, padding_bytes = 0;2120 2121	jpeg_addr.cb = 0;2122	jpeg_addr.cr = 0;2123 2124	pix_size = ctx->cap_q.w * ctx->cap_q.h;2125 2126	if (ctx->mode == S5P_JPEG_ENCODE) {2127		vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);2128		fmt = ctx->out_q.fmt;2129		if (ctx->out_q.w % 2 && fmt->h_align > 0)2130			padding_bytes = ctx->out_q.h;2131	} else {2132		fmt = ctx->cap_q.fmt;2133		vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);2134	}2135 2136	jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);2137 2138	if (fmt->colplanes == 2) {2139		jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;2140	} else if (fmt->colplanes == 3) {2141		jpeg_addr.cb = jpeg_addr.y + pix_size;2142		if (fmt->fourcc == V4L2_PIX_FMT_YUV420)2143			jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;2144		else2145			jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;2146	}2147 2148	exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);2149}2150 2151static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)2152{2153	struct s5p_jpeg *jpeg = ctx->jpeg;2154	struct vb2_v4l2_buffer *vb;2155	unsigned int jpeg_addr = 0;2156 2157	if (ctx->mode == S5P_JPEG_ENCODE)2158		vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);2159	else2160		vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);2161 2162	jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);2163	if (jpeg->variant->version == SJPEG_EXYNOS5433 &&2164	    ctx->mode == S5P_JPEG_DECODE)2165		jpeg_addr += ctx->out_q.sos;2166	exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);2167}2168 2169static inline void exynos4_jpeg_set_img_fmt(void __iomem *base,2170					    unsigned int img_fmt)2171{2172	__exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4);2173}2174 2175static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base,2176					       unsigned int img_fmt)2177{2178	__exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433);2179}2180 2181static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base,2182						unsigned int out_fmt)2183{2184	__exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4);2185}2186 2187static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base,2188						   unsigned int out_fmt)2189{2190	__exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433);2191}2192 2193static void exynos4_jpeg_device_run(void *priv)2194{2195	struct s5p_jpeg_ctx *ctx = priv;2196	struct s5p_jpeg *jpeg = ctx->jpeg;2197	unsigned int bitstream_size;2198	unsigned long flags;2199 2200	spin_lock_irqsave(&jpeg->slock, flags);2201 2202	if (ctx->mode == S5P_JPEG_ENCODE) {2203		exynos4_jpeg_sw_reset(jpeg->regs);2204		exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version);2205		exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);2206 2207		exynos4_jpeg_set_huff_tbl(jpeg->regs);2208 2209		/*2210		 * JPEG IP allows storing 4 quantization tables2211		 * We fill table 0 for luma and table 1 for chroma2212		 */2213		exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);2214		exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);2215 2216		exynos4_jpeg_set_encode_tbl_select(jpeg->regs,2217							ctx->compr_quality);2218		exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,2219							ctx->cap_q.h);2220 2221		if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) {2222			exynos4_jpeg_set_enc_out_fmt(jpeg->regs,2223						     ctx->subsampling);2224			exynos4_jpeg_set_img_fmt(jpeg->regs,2225						 ctx->out_q.fmt->fourcc);2226		} else {2227			exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,2228							ctx->subsampling);2229			exynos5433_jpeg_set_img_fmt(jpeg->regs,2230						    ctx->out_q.fmt->fourcc);2231		}2232		exynos4_jpeg_set_img_addr(ctx);2233		exynos4_jpeg_set_jpeg_addr(ctx);2234		exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,2235							ctx->out_q.fmt->fourcc);2236	} else {2237		exynos4_jpeg_sw_reset(jpeg->regs);2238		exynos4_jpeg_set_interrupt(jpeg->regs,2239					   jpeg->variant->version);2240		exynos4_jpeg_set_img_addr(ctx);2241		exynos4_jpeg_set_jpeg_addr(ctx);2242 2243		if (jpeg->variant->version == SJPEG_EXYNOS5433) {2244			exynos4_jpeg_parse_huff_tbl(ctx);2245			exynos4_jpeg_parse_decode_h_tbl(ctx);2246 2247			exynos4_jpeg_parse_q_tbl(ctx);2248			exynos4_jpeg_parse_decode_q_tbl(ctx);2249 2250			exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);2251 2252			exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,2253					ctx->cap_q.h);2254			exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,2255							ctx->subsampling);2256			exynos5433_jpeg_set_img_fmt(jpeg->regs,2257						    ctx->cap_q.fmt->fourcc);2258			bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16);2259		} else {2260			exynos4_jpeg_set_img_fmt(jpeg->regs,2261						 ctx->cap_q.fmt->fourcc);2262			bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);2263		}2264 2265		exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);2266	}2267 2268	exynos4_jpeg_set_sys_int_enable(jpeg->regs, 1);2269	exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);2270 2271	spin_unlock_irqrestore(&jpeg->slock, flags);2272}2273 2274static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)2275{2276	struct s5p_jpeg *jpeg = ctx->jpeg;2277	struct s5p_jpeg_fmt *fmt;2278	struct vb2_v4l2_buffer *vb;2279	struct s5p_jpeg_addr jpeg_addr = {};2280	u32 pix_size;2281 2282	pix_size = ctx->cap_q.w * ctx->cap_q.h;2283 2284	if (ctx->mode == S5P_JPEG_ENCODE) {2285		vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);2286		fmt = ctx->out_q.fmt;2287	} else {2288		vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);2289		fmt = ctx->cap_q.fmt;2290	}2291 2292	jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);2293 2294	if (fmt->colplanes == 2) {2295		jpeg_addr.cb = jpeg_addr.y + pix_size;2296	} else if (fmt->colplanes == 3) {2297		jpeg_addr.cb = jpeg_addr.y + pix_size;2298		if (fmt->fourcc == V4L2_PIX_FMT_YUV420)2299			jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;2300		else2301			jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;2302	}2303 2304	exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);2305}2306 2307static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)2308{2309	struct s5p_jpeg *jpeg = ctx->jpeg;2310	struct vb2_v4l2_buffer *vb;2311	unsigned int jpeg_addr = 0;2312 2313	if (ctx->mode == S5P_JPEG_ENCODE)2314		vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);2315	else2316		vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);2317 2318	jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);2319	exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);2320}2321 2322static void exynos3250_jpeg_device_run(void *priv)2323{2324	struct s5p_jpeg_ctx *ctx = priv;2325	struct s5p_jpeg *jpeg = ctx->jpeg;2326	unsigned long flags;2327 2328	spin_lock_irqsave(&ctx->jpeg->slock, flags);2329 2330	exynos3250_jpeg_reset(jpeg->regs);2331	exynos3250_jpeg_set_dma_num(jpeg->regs);2332	exynos3250_jpeg_poweron(jpeg->regs);2333	exynos3250_jpeg_clk_set(jpeg->regs);2334	exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);2335 2336	if (ctx->mode == S5P_JPEG_ENCODE) {2337		exynos3250_jpeg_input_raw_fmt(jpeg->regs,2338					      ctx->out_q.fmt->fourcc);2339		exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);2340 2341		/*2342		 * JPEG IP allows storing 4 quantization tables2343		 * We fill table 0 for luma and table 1 for chroma2344		 */2345		s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);2346		s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);2347		/* use table 0 for Y */2348		exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);2349		/* use table 1 for Cb and Cr*/2350		exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);2351		exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);2352 2353		/*2354		 * Some SoCs require setting Huffman tables before each run2355		 */2356		if (jpeg->variant->htbl_reinit) {2357			s5p_jpeg_set_hdctbl(jpeg->regs);2358			s5p_jpeg_set_hdctblg(jpeg->regs);2359			s5p_jpeg_set_hactbl(jpeg->regs);2360			s5p_jpeg_set_hactblg(jpeg->regs);2361		}2362 2363		/* Y, Cb, Cr use Huffman table 0 */2364		exynos3250_jpeg_htbl_ac(jpeg->regs, 1);2365		exynos3250_jpeg_htbl_dc(jpeg->regs, 1);2366		exynos3250_jpeg_htbl_ac(jpeg->regs, 2);2367		exynos3250_jpeg_htbl_dc(jpeg->regs, 2);2368		exynos3250_jpeg_htbl_ac(jpeg->regs, 3);2369		exynos3250_jpeg_htbl_dc(jpeg->regs, 3);2370 2371		exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);2372		exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);2373		exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,2374								ctx->out_q.w);2375		exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,2376							ctx->crop_rect.top);2377		exynos3250_jpeg_set_img_addr(ctx);2378		exynos3250_jpeg_set_jpeg_addr(ctx);2379		exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);2380 2381		/* ultimately comes from sizeimage from userspace */2382		exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);2383 2384		if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||2385		    ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||2386		    ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)2387			exynos3250_jpeg_set_y16(jpeg->regs, true);2388	} else {2389		exynos3250_jpeg_set_img_addr(ctx);2390		exynos3250_jpeg_set_jpeg_addr(ctx);2391		exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,2392								ctx->cap_q.w);2393		exynos3250_jpeg_offset(jpeg->regs, 0, 0);2394		exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,2395							ctx->scale_factor);2396		exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);2397		exynos3250_jpeg_output_raw_fmt(jpeg->regs,2398						ctx->cap_q.fmt->fourcc);2399	}2400 2401	exynos3250_jpeg_interrupts_enable(jpeg->regs);2402 2403	/* JPEG RGB to YCbCr conversion matrix */2404	exynos3250_jpeg_coef(jpeg->regs, ctx->mode);2405 2406	exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);2407	jpeg->irq_status = 0;2408	exynos3250_jpeg_start(jpeg->regs);2409 2410	spin_unlock_irqrestore(&ctx->jpeg->slock, flags);2411}2412 2413static int s5p_jpeg_job_ready(void *priv)2414{2415	struct s5p_jpeg_ctx *ctx = priv;2416 2417	if (ctx->mode == S5P_JPEG_DECODE) {2418		/*2419		 * We have only one input buffer and one output buffer. If there2420		 * is a resolution change event, no need to continue decoding.2421		 */2422		if (ctx->state == JPEGCTX_RESOLUTION_CHANGE)2423			return 0;2424 2425		return ctx->hdr_parsed;2426	}2427 2428	return 1;2429}2430 2431static const struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {2432	.device_run	= s5p_jpeg_device_run,2433	.job_ready	= s5p_jpeg_job_ready,2434};2435 2436static const struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {2437	.device_run	= exynos3250_jpeg_device_run,2438	.job_ready	= s5p_jpeg_job_ready,2439};2440 2441static const struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {2442	.device_run	= exynos4_jpeg_device_run,2443	.job_ready	= s5p_jpeg_job_ready,2444};2445 2446/*2447 * ============================================================================2448 * Queue operations2449 * ============================================================================2450 */2451 2452static int s5p_jpeg_queue_setup(struct vb2_queue *vq,2453			   unsigned int *nbuffers, unsigned int *nplanes,2454			   unsigned int sizes[], struct device *alloc_devs[])2455{2456	struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);2457	struct s5p_jpeg_q_data *q_data = NULL;2458	unsigned int size, count = *nbuffers;2459 2460	q_data = get_q_data(ctx, vq->type);2461	BUG_ON(q_data == NULL);2462 2463	size = q_data->size;2464 2465	/*2466	 * header is parsed during decoding and parsed information stored2467	 * in the context so we do not allow another buffer to overwrite it2468	 */2469	if (ctx->mode == S5P_JPEG_DECODE)2470		count = 1;2471 2472	*nbuffers = count;2473	*nplanes = 1;2474	sizes[0] = size;2475 2476	return 0;2477}2478 2479static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)2480{2481	struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);2482	struct s5p_jpeg_q_data *q_data = NULL;2483 2484	q_data = get_q_data(ctx, vb->vb2_queue->type);2485	BUG_ON(q_data == NULL);2486 2487	if (vb2_plane_size(vb, 0) < q_data->size) {2488		pr_err("%s data will not fit into plane (%lu < %lu)\n",2489				__func__, vb2_plane_size(vb, 0),2490				(long)q_data->size);2491		return -EINVAL;2492	}2493 2494	vb2_set_plane_payload(vb, 0, q_data->size);2495 2496	return 0;2497}2498 2499static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx)2500{2501	struct s5p_jpeg_q_data *q_data = &ctx->cap_q;2502 2503	q_data->w = ctx->out_q.w;2504	q_data->h = ctx->out_q.h;2505 2506	/*2507	 * This call to jpeg_bound_align_image() takes care of width and2508	 * height values alignment when user space calls the QBUF of2509	 * OUTPUT buffer after the S_FMT of CAPTURE buffer.2510	 * Please note that on Exynos4x12 SoCs, resigning from executing2511	 * S_FMT on capture buffer for each JPEG image can result in a2512	 * hardware hangup if subsampling is lower than the one of input2513	 * JPEG.2514	 */2515	jpeg_bound_align_image(ctx, &q_data->w, S5P_JPEG_MIN_WIDTH,2516			       S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align,2517			       &q_data->h, S5P_JPEG_MIN_HEIGHT,2518			       S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align);2519 2520	q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;2521}2522 2523static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)2524{2525	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);2526	struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);2527 2528	if (ctx->mode == S5P_JPEG_DECODE &&2529	    vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {2530		static const struct v4l2_event ev_src_ch = {2531			.type = V4L2_EVENT_SOURCE_CHANGE,2532			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,2533		};2534		struct vb2_queue *dst_vq;2535		u32 ori_w;2536		u32 ori_h;2537 2538		dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,2539					 V4L2_BUF_TYPE_VIDEO_CAPTURE);2540		ori_w = ctx->out_q.w;2541		ori_h = ctx->out_q.h;2542 2543		ctx->hdr_parsed = s5p_jpeg_parse_hdr(&ctx->out_q,2544		     (unsigned long)vb2_plane_vaddr(vb, 0),2545		     min((unsigned long)ctx->out_q.size,2546			 vb2_get_plane_payload(vb, 0)), ctx);2547		if (!ctx->hdr_parsed) {2548			vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);2549			return;2550		}2551 2552		/*2553		 * If there is a resolution change event, only update capture2554		 * queue when it is not streaming. Otherwise, update it in2555		 * STREAMOFF. See s5p_jpeg_stop_streaming for detail.2556		 */2557		if (ctx->out_q.w != ori_w || ctx->out_q.h != ori_h) {2558			v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);2559			if (vb2_is_streaming(dst_vq))2560				ctx->state = JPEGCTX_RESOLUTION_CHANGE;2561			else2562				s5p_jpeg_set_capture_queue_data(ctx);2563		}2564	}2565 2566	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);2567}2568 2569static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)2570{2571	struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);2572 2573	return pm_runtime_resume_and_get(ctx->jpeg->dev);2574}2575 2576static void s5p_jpeg_stop_streaming(struct vb2_queue *q)2577{2578	struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);2579 2580	/*2581	 * STREAMOFF is an acknowledgment for resolution change event.2582	 * Before STREAMOFF, we still have to return the old resolution and2583	 * subsampling. Update capture queue when the stream is off.2584	 */2585	if (ctx->state == JPEGCTX_RESOLUTION_CHANGE &&2586	    q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {2587		s5p_jpeg_set_capture_queue_data(ctx);2588		ctx->state = JPEGCTX_RUNNING;2589	}2590 2591	pm_runtime_put(ctx->jpeg->dev);2592}2593 2594static const struct vb2_ops s5p_jpeg_qops = {2595	.queue_setup		= s5p_jpeg_queue_setup,2596	.buf_prepare		= s5p_jpeg_buf_prepare,2597	.buf_queue		= s5p_jpeg_buf_queue,2598	.wait_prepare		= vb2_ops_wait_prepare,2599	.wait_finish		= vb2_ops_wait_finish,2600	.start_streaming	= s5p_jpeg_start_streaming,2601	.stop_streaming		= s5p_jpeg_stop_streaming,2602};2603 2604static int queue_init(void *priv, struct vb2_queue *src_vq,2605		      struct vb2_queue *dst_vq)2606{2607	struct s5p_jpeg_ctx *ctx = priv;2608	int ret;2609 2610	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;2611	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;2612	src_vq->drv_priv = ctx;2613	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);2614	src_vq->ops = &s5p_jpeg_qops;2615	src_vq->mem_ops = &vb2_dma_contig_memops;2616	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;2617	src_vq->lock = &ctx->jpeg->lock;2618	src_vq->dev = ctx->jpeg->dev;2619 2620	ret = vb2_queue_init(src_vq);2621	if (ret)2622		return ret;2623 2624	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;2625	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;2626	dst_vq->drv_priv = ctx;2627	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);2628	dst_vq->ops = &s5p_jpeg_qops;2629	dst_vq->mem_ops = &vb2_dma_contig_memops;2630	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;2631	dst_vq->lock = &ctx->jpeg->lock;2632	dst_vq->dev = ctx->jpeg->dev;2633 2634	return vb2_queue_init(dst_vq);2635}2636 2637/*2638 * ============================================================================2639 * ISR2640 * ============================================================================2641 */2642 2643static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)2644{2645	struct s5p_jpeg *jpeg = dev_id;2646	struct s5p_jpeg_ctx *curr_ctx;2647	struct vb2_v4l2_buffer *src_buf, *dst_buf;2648	unsigned long payload_size = 0;2649	enum vb2_buffer_state state = VB2_BUF_STATE_DONE;2650	bool enc_jpeg_too_large = false;2651	bool timer_elapsed = false;2652	bool op_completed = false;2653 2654	spin_lock(&jpeg->slock);2655 2656	curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);2657 2658	src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);2659	dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);2660 2661	if (curr_ctx->mode == S5P_JPEG_ENCODE)2662		enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);2663	timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);2664	op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);2665	if (curr_ctx->mode == S5P_JPEG_DECODE)2666		op_completed = op_completed &&2667					s5p_jpeg_stream_stat_ok(jpeg->regs);2668 2669	if (enc_jpeg_too_large) {2670		state = VB2_BUF_STATE_ERROR;2671		s5p_jpeg_clear_enc_stream_stat(jpeg->regs);2672	} else if (timer_elapsed) {2673		state = VB2_BUF_STATE_ERROR;2674		s5p_jpeg_clear_timer_stat(jpeg->regs);2675	} else if (!op_completed) {2676		state = VB2_BUF_STATE_ERROR;2677	} else {2678		payload_size = s5p_jpeg_compressed_size(jpeg->regs);2679	}2680 2681	dst_buf->timecode = src_buf->timecode;2682	dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;2683	dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;2684	dst_buf->flags |=2685		src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;2686 2687	v4l2_m2m_buf_done(src_buf, state);2688	if (curr_ctx->mode == S5P_JPEG_ENCODE)2689		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);2690	v4l2_m2m_buf_done(dst_buf, state);2691 2692	curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);2693	spin_unlock(&jpeg->slock);2694 2695	s5p_jpeg_clear_int(jpeg->regs);2696 2697	v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);2698	return IRQ_HANDLED;2699}2700 2701static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)2702{2703	unsigned int int_status;2704	struct vb2_v4l2_buffer *src_vb, *dst_vb;2705	struct s5p_jpeg *jpeg = priv;2706	struct s5p_jpeg_ctx *curr_ctx;2707	unsigned long payload_size = 0;2708 2709	spin_lock(&jpeg->slock);2710 2711	exynos4_jpeg_set_sys_int_enable(jpeg->regs, 0);2712 2713	curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);2714 2715	src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);2716	dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);2717 2718	int_status = exynos4_jpeg_get_int_status(jpeg->regs);2719 2720	if (int_status) {2721		switch (int_status & 0x1f) {2722		case 0x1:2723			jpeg->irq_ret = ERR_PROT;2724			break;2725		case 0x2:2726			jpeg->irq_ret = OK_ENC_OR_DEC;2727			break;2728		case 0x4:2729			jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;2730			break;2731		case 0x8:2732			jpeg->irq_ret = ERR_MULTI_SCAN;2733			break;2734		case 0x10:2735			jpeg->irq_ret = ERR_FRAME;2736			break;2737		default:2738			jpeg->irq_ret = ERR_UNKNOWN;2739			break;2740		}2741	} else {2742		jpeg->irq_ret = ERR_UNKNOWN;2743	}2744 2745	if (jpeg->irq_ret == OK_ENC_OR_DEC) {2746		if (curr_ctx->mode == S5P_JPEG_ENCODE) {2747			payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);2748			vb2_set_plane_payload(&dst_vb->vb2_buf,2749					0, payload_size);2750		}2751		v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);2752		v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);2753	} else {2754		v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);2755		v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);2756	}2757 2758	if (jpeg->variant->version == SJPEG_EXYNOS4)2759		curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);2760 2761	exynos4_jpeg_set_enc_dec_mode(jpeg->regs, S5P_JPEG_DISABLE);2762 2763	spin_unlock(&jpeg->slock);2764 2765	v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);2766	return IRQ_HANDLED;2767}2768 2769static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)2770{2771	struct s5p_jpeg *jpeg = dev_id;2772	struct s5p_jpeg_ctx *curr_ctx;2773	struct vb2_v4l2_buffer *src_buf, *dst_buf;2774	unsigned long payload_size = 0;2775	enum vb2_buffer_state state = VB2_BUF_STATE_DONE;2776	bool interrupt_timeout = false;2777	bool stream_error = false;2778	u32 irq_status;2779 2780	spin_lock(&jpeg->slock);2781 2782	irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);2783	if (irq_status & EXYNOS3250_TIMER_INT_STAT) {2784		exynos3250_jpeg_clear_timer_status(jpeg->regs);2785		interrupt_timeout = true;2786		dev_err(jpeg->dev, "Interrupt timeout occurred.\n");2787	}2788 2789	irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);2790	exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);2791 2792	jpeg->irq_status |= irq_status;2793 2794	if (jpeg->variant->version == SJPEG_EXYNOS5420 &&2795	    irq_status & EXYNOS3250_STREAM_STAT) {2796		stream_error = true;2797		dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n");2798	}2799 2800	curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);2801 2802	if (!curr_ctx)2803		goto exit_unlock;2804 2805	if ((irq_status & EXYNOS3250_HEADER_STAT) &&2806	    (curr_ctx->mode == S5P_JPEG_DECODE)) {2807		exynos3250_jpeg_rstart(jpeg->regs);2808		goto exit_unlock;2809	}2810 2811	if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |2812				EXYNOS3250_WDMA_DONE |2813				EXYNOS3250_RDMA_DONE |2814				EXYNOS3250_RESULT_STAT))2815		payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);2816	else if (interrupt_timeout || stream_error)2817		state = VB2_BUF_STATE_ERROR;2818	else2819		goto exit_unlock;2820 2821	src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);2822	dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);2823 2824	dst_buf->timecode = src_buf->timecode;2825	dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;2826 2827	v4l2_m2m_buf_done(src_buf, state);2828	if (curr_ctx->mode == S5P_JPEG_ENCODE)2829		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);2830	v4l2_m2m_buf_done(dst_buf, state);2831 2832	curr_ctx->subsampling =2833			exynos3250_jpeg_get_subsampling_mode(jpeg->regs);2834 2835	spin_unlock(&jpeg->slock);2836 2837	v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);2838	return IRQ_HANDLED;2839 2840exit_unlock:2841	spin_unlock(&jpeg->slock);2842	return IRQ_HANDLED;2843}2844 2845static void *jpeg_get_drv_data(struct device *dev);2846 2847/*2848 * ============================================================================2849 * Driver basic infrastructure2850 * ============================================================================2851 */2852 2853static int s5p_jpeg_probe(struct platform_device *pdev)2854{2855	struct s5p_jpeg *jpeg;2856	int i, ret;2857 2858	/* JPEG IP abstraction struct */2859	jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);2860	if (!jpeg)2861		return -ENOMEM;2862 2863	jpeg->variant = jpeg_get_drv_data(&pdev->dev);2864	if (!jpeg->variant)2865		return -ENODEV;2866 2867	mutex_init(&jpeg->lock);2868	spin_lock_init(&jpeg->slock);2869	jpeg->dev = &pdev->dev;2870 2871	/* memory-mapped registers */2872	jpeg->regs = devm_platform_ioremap_resource(pdev, 0);2873	if (IS_ERR(jpeg->regs))2874		return PTR_ERR(jpeg->regs);2875 2876	/* interrupt service routine registration */2877	jpeg->irq = ret = platform_get_irq(pdev, 0);2878	if (ret < 0)2879		return ret;2880 2881	ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,2882				0, dev_name(&pdev->dev), jpeg);2883	if (ret) {2884		dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);2885		return ret;2886	}2887 2888	/* clocks */2889	for (i = 0; i < jpeg->variant->num_clocks; i++) {2890		jpeg->clocks[i] = devm_clk_get(&pdev->dev,2891					      jpeg->variant->clk_names[i]);2892		if (IS_ERR(jpeg->clocks[i])) {2893			dev_err(&pdev->dev, "failed to get clock: %s\n",2894				jpeg->variant->clk_names[i]);2895			return PTR_ERR(jpeg->clocks[i]);2896		}2897	}2898 2899	/* v4l2 device */2900	ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);2901	if (ret) {2902		dev_err(&pdev->dev, "Failed to register v4l2 device\n");2903		return ret;2904	}2905 2906	/* mem2mem device */2907	jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);2908	if (IS_ERR(jpeg->m2m_dev)) {2909		v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");2910		ret = PTR_ERR(jpeg->m2m_dev);2911		goto device_register_rollback;2912	}2913 2914	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));2915 2916	/* JPEG encoder /dev/videoX node */2917	jpeg->vfd_encoder = video_device_alloc();2918	if (!jpeg->vfd_encoder) {2919		v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");2920		ret = -ENOMEM;2921		goto m2m_init_rollback;2922	}2923	snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),2924				"%s-enc", S5P_JPEG_M2M_NAME);2925	jpeg->vfd_encoder->fops		= &s5p_jpeg_fops;2926	jpeg->vfd_encoder->ioctl_ops	= &s5p_jpeg_ioctl_ops;2927	jpeg->vfd_encoder->minor	= -1;2928	jpeg->vfd_encoder->release	= video_device_release;2929	jpeg->vfd_encoder->lock		= &jpeg->lock;2930	jpeg->vfd_encoder->v4l2_dev	= &jpeg->v4l2_dev;2931	jpeg->vfd_encoder->vfl_dir	= VFL_DIR_M2M;2932	jpeg->vfd_encoder->device_caps	= V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;2933 2934	ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_VIDEO, -1);2935	if (ret) {2936		v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");2937		video_device_release(jpeg->vfd_encoder);2938		goto m2m_init_rollback;2939	}2940 2941	video_set_drvdata(jpeg->vfd_encoder, jpeg);2942	v4l2_info(&jpeg->v4l2_dev,2943		  "encoder device registered as /dev/video%d\n",2944		  jpeg->vfd_encoder->num);2945 2946	/* JPEG decoder /dev/videoX node */2947	jpeg->vfd_decoder = video_device_alloc();2948	if (!jpeg->vfd_decoder) {2949		v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");2950		ret = -ENOMEM;2951		goto enc_vdev_register_rollback;2952	}2953	snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),2954				"%s-dec", S5P_JPEG_M2M_NAME);2955	jpeg->vfd_decoder->fops		= &s5p_jpeg_fops;2956	jpeg->vfd_decoder->ioctl_ops	= &s5p_jpeg_ioctl_ops;2957	jpeg->vfd_decoder->minor	= -1;2958	jpeg->vfd_decoder->release	= video_device_release;2959	jpeg->vfd_decoder->lock		= &jpeg->lock;2960	jpeg->vfd_decoder->v4l2_dev	= &jpeg->v4l2_dev;2961	jpeg->vfd_decoder->vfl_dir	= VFL_DIR_M2M;2962	jpeg->vfd_decoder->device_caps	= V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;2963 2964	ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_VIDEO, -1);2965	if (ret) {2966		v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");2967		video_device_release(jpeg->vfd_decoder);2968		goto enc_vdev_register_rollback;2969	}2970 2971	video_set_drvdata(jpeg->vfd_decoder, jpeg);2972	v4l2_info(&jpeg->v4l2_dev,2973		  "decoder device registered as /dev/video%d\n",2974		  jpeg->vfd_decoder->num);2975 2976	/* final statements & power management */2977	platform_set_drvdata(pdev, jpeg);2978 2979	pm_runtime_enable(&pdev->dev);2980 2981	v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");2982 2983	return 0;2984 2985enc_vdev_register_rollback:2986	video_unregister_device(jpeg->vfd_encoder);2987 2988m2m_init_rollback:2989	v4l2_m2m_release(jpeg->m2m_dev);2990 2991device_register_rollback:2992	v4l2_device_unregister(&jpeg->v4l2_dev);2993 2994	return ret;2995}2996 2997static void s5p_jpeg_remove(struct platform_device *pdev)2998{2999	struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);3000	int i;3001 3002	pm_runtime_disable(jpeg->dev);3003 3004	video_unregister_device(jpeg->vfd_decoder);3005	video_unregister_device(jpeg->vfd_encoder);3006	vb2_dma_contig_clear_max_seg_size(&pdev->dev);3007	v4l2_m2m_release(jpeg->m2m_dev);3008	v4l2_device_unregister(&jpeg->v4l2_dev);3009 3010	if (!pm_runtime_status_suspended(&pdev->dev)) {3011		for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)3012			clk_disable_unprepare(jpeg->clocks[i]);3013	}3014}3015 3016#ifdef CONFIG_PM3017static int s5p_jpeg_runtime_suspend(struct device *dev)3018{3019	struct s5p_jpeg *jpeg = dev_get_drvdata(dev);3020	int i;3021 3022	for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)3023		clk_disable_unprepare(jpeg->clocks[i]);3024 3025	return 0;3026}3027 3028static int s5p_jpeg_runtime_resume(struct device *dev)3029{3030	struct s5p_jpeg *jpeg = dev_get_drvdata(dev);3031	unsigned long flags;3032	int i, ret;3033 3034	for (i = 0; i < jpeg->variant->num_clocks; i++) {3035		ret = clk_prepare_enable(jpeg->clocks[i]);3036		if (ret) {3037			while (--i >= 0)3038				clk_disable_unprepare(jpeg->clocks[i]);3039			return ret;3040		}3041	}3042 3043	spin_lock_irqsave(&jpeg->slock, flags);3044 3045	/*3046	 * JPEG IP allows storing two Huffman tables for each component.3047	 * We fill table 0 for each component and do this here only3048	 * for S5PC210 and Exynos3250 SoCs. Exynos4x12 and Exynos542x SoC3049	 * require programming their Huffman tables each time the encoding3050	 * process is initialized, and thus it is accomplished in the3051	 * device_run callback of m2m_ops.3052	 */3053	if (!jpeg->variant->htbl_reinit) {3054		s5p_jpeg_set_hdctbl(jpeg->regs);3055		s5p_jpeg_set_hdctblg(jpeg->regs);3056		s5p_jpeg_set_hactbl(jpeg->regs);3057		s5p_jpeg_set_hactblg(jpeg->regs);3058	}3059 3060	spin_unlock_irqrestore(&jpeg->slock, flags);3061 3062	return 0;3063}3064#endif /* CONFIG_PM */3065 3066static const struct dev_pm_ops s5p_jpeg_pm_ops = {3067	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,3068				pm_runtime_force_resume)3069	SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume,3070			   NULL)3071};3072 3073static struct s5p_jpeg_variant s5p_jpeg_drvdata = {3074	.version	= SJPEG_S5P,3075	.jpeg_irq	= s5p_jpeg_irq,3076	.m2m_ops	= &s5p_jpeg_m2m_ops,3077	.fmt_ver_flag	= SJPEG_FMT_FLAG_S5P,3078	.clk_names	= {"jpeg"},3079	.num_clocks	= 1,3080};3081 3082static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {3083	.version	= SJPEG_EXYNOS3250,3084	.jpeg_irq	= exynos3250_jpeg_irq,3085	.m2m_ops	= &exynos3250_jpeg_m2m_ops,3086	.fmt_ver_flag	= SJPEG_FMT_FLAG_EXYNOS3250,3087	.hw3250_compat	= 1,3088	.clk_names	= {"jpeg", "sclk"},3089	.num_clocks	= 2,3090};3091 3092static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {3093	.version	= SJPEG_EXYNOS4,3094	.jpeg_irq	= exynos4_jpeg_irq,3095	.m2m_ops	= &exynos4_jpeg_m2m_ops,3096	.fmt_ver_flag	= SJPEG_FMT_FLAG_EXYNOS4,3097	.htbl_reinit	= 1,3098	.clk_names	= {"jpeg"},3099	.num_clocks	= 1,3100	.hw_ex4_compat	= 1,3101};3102 3103static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {3104	.version	= SJPEG_EXYNOS5420,3105	.jpeg_irq	= exynos3250_jpeg_irq,		/* intentionally 3250 */3106	.m2m_ops	= &exynos3250_jpeg_m2m_ops,	/* intentionally 3250 */3107	.fmt_ver_flag	= SJPEG_FMT_FLAG_EXYNOS3250,	/* intentionally 3250 */3108	.hw3250_compat	= 1,3109	.htbl_reinit	= 1,3110	.clk_names	= {"jpeg"},3111	.num_clocks	= 1,3112};3113 3114static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = {3115	.version	= SJPEG_EXYNOS5433,3116	.jpeg_irq	= exynos4_jpeg_irq,3117	.m2m_ops	= &exynos4_jpeg_m2m_ops,3118	.fmt_ver_flag	= SJPEG_FMT_FLAG_EXYNOS4,3119	.htbl_reinit	= 1,3120	.clk_names	= {"pclk", "aclk", "aclk_xiu", "sclk"},3121	.num_clocks	= 4,3122	.hw_ex4_compat	= 1,3123};3124 3125static const struct of_device_id samsung_jpeg_match[] = {3126	{3127		.compatible = "samsung,s5pv210-jpeg",3128		.data = &s5p_jpeg_drvdata,3129	}, {3130		.compatible = "samsung,exynos3250-jpeg",3131		.data = &exynos3250_jpeg_drvdata,3132	}, {3133		.compatible = "samsung,exynos4210-jpeg",3134		.data = &exynos4_jpeg_drvdata,3135	}, {3136		.compatible = "samsung,exynos4212-jpeg",3137		.data = &exynos4_jpeg_drvdata,3138	}, {3139		.compatible = "samsung,exynos5420-jpeg",3140		.data = &exynos5420_jpeg_drvdata,3141	}, {3142		.compatible = "samsung,exynos5433-jpeg",3143		.data = &exynos5433_jpeg_drvdata,3144	},3145	{},3146};3147 3148MODULE_DEVICE_TABLE(of, samsung_jpeg_match);3149 3150static void *jpeg_get_drv_data(struct device *dev)3151{3152	struct s5p_jpeg_variant *driver_data = NULL;3153	const struct of_device_id *match;3154 3155	if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)3156		return &s5p_jpeg_drvdata;3157 3158	match = of_match_node(samsung_jpeg_match, dev->of_node);3159 3160	if (match)3161		driver_data = (struct s5p_jpeg_variant *)match->data;3162 3163	return driver_data;3164}3165 3166static struct platform_driver s5p_jpeg_driver = {3167	.probe = s5p_jpeg_probe,3168	.remove_new = s5p_jpeg_remove,3169	.driver = {3170		.of_match_table	= samsung_jpeg_match,3171		.name		= S5P_JPEG_M2M_NAME,3172		.pm		= &s5p_jpeg_pm_ops,3173	},3174};3175 3176module_platform_driver(s5p_jpeg_driver);3177 3178MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>");3179MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");3180MODULE_DESCRIPTION("Samsung JPEG codec driver");3181MODULE_LICENSE("GPL");3182