diff options
author | Janghyuck Kim <janghyuck.kim@samsung.com> | 2010-08-10 16:31:34 +0900 |
---|---|---|
committer | Arve Hjønnevåg <arve@android.com> | 2011-11-17 17:40:48 -0800 |
commit | 27f1fec5123fa480604c747d73639027c5e5ae93 (patch) | |
tree | 675007c12eb001718c8f22ea6bd1bed68d697fec | |
parent | fc7408d4d5e1dd43c4fa204a6d45c0b843496b52 (diff) | |
download | kernel_samsung_crespo-27f1fec5123fa480604c747d73639027c5e5ae93.zip kernel_samsung_crespo-27f1fec5123fa480604c747d73639027c5e5ae93.tar.gz kernel_samsung_crespo-27f1fec5123fa480604c747d73639027c5e5ae93.tar.bz2 |
S5PC110: JPEG: Add JPEG driver files
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/Kconfig | 15 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/Makefile | 10 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_conf.h | 259 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_mem.c | 62 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_mem.h | 144 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_misc.c | 80 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_misc.h | 34 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_opr.c | 310 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/jpg_opr.h | 153 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/regs-jpeg.h | 147 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c | 536 | ||||
-rw-r--r-- | drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h | 33 |
12 files changed, 1783 insertions, 0 deletions
diff --git a/drivers/media/video/samsung/jpeg_v2/Kconfig b/drivers/media/video/samsung/jpeg_v2/Kconfig new file mode 100644 index 0000000..291aa90 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/Kconfig @@ -0,0 +1,15 @@ +# +# Configuration for JPEG +# + +config VIDEO_JPEG_V2 + bool "Samsung JPEG driver" + depends on VIDEO_SAMSUNG + default n + ---help--- + This is a JPEG for Samsung S5PV210 + +config VIDEO_JPEG_DEBUG + bool "print JPEG debug message" + depends on VIDEO_JPEG_V2 + default n diff --git a/drivers/media/video/samsung/jpeg_v2/Makefile b/drivers/media/video/samsung/jpeg_v2/Makefile new file mode 100644 index 0000000..d7ed17f --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/Makefile @@ -0,0 +1,10 @@ +################################################# +# Makefile for JPEG_V2 +# 2009 (C) Samsung Electronics +# Author : Jaeryul peter Oh <jaeryul.oh@samsung.com> +################################################# + +obj-$(CONFIG_VIDEO_JPEG_V2) += jpg_mem.o jpg_misc.o jpg_opr.o s3c-jpeg.o + +EXTRA_CFLAGS += -Idrivers/media/video + diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_conf.h b/drivers/media/video/samsung/jpeg_v2/jpg_conf.h new file mode 100644 index 0000000..90d8c2d --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_conf.h @@ -0,0 +1,259 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg-conf.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Definition Quantization Table for Jpeg encoder/docoder + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __JPG_CONF_H__ +#define __JPG_CONF_H__ + + +const unsigned char qtbl_luminance[4][64] = { + // level 1 - high quality + { + 8, 6, 6, 8, 12, 14, 16, 17, + 6, 6, 6, 8, 10, 13, 12, 15, + 6, 6, 7, 8, 13, 14, 18, 24, + 8, 8, 8, 14, 13, 19, 24, 35, + 12, 10, 13, 13, 20, 26, 34, 39, + 14, 13, 14, 19, 26, 34, 39, 39, + 16, 12, 18, 24, 34, 39, 39, 39, + 17, 15, 24, 35, 39, 39, 39, 39 + }, + + // level 2 + { + 12, 8, 8, 12, 17, 21, 24, 23, + 8, 9, 9, 11, 15, 19, 18, 23, + 8, 9, 10, 12, 19, 20, 27, 36, + 12, 11, 12, 21, 20, 28, 36, 53, + 17, 15, 19, 20, 30, 39, 51, 59, + 21, 19, 20, 28, 39, 51, 59, 59, + 24, 18, 27, 36, 51, 59, 59, 59, + 23, 23, 36, 53, 59, 59, 59, 59 + }, + + // level 3 + { + 16, 11, 11, 16, 23, 27, 31, 30, + 11, 12, 12, 15, 20, 23, 23, 30, + 11, 12, 13, 16, 23, 26, 35, 47, + 16, 15, 16, 23, 26, 37, 47, 64, + 23, 20, 23, 26, 39, 51, 64, 64, + 27, 23, 26, 37, 51, 64, 64, 64, + 31, 23, 35, 47, 64, 64, 64, 64, + 30, 30, 47, 64, 64, 64, 64, 64 + + }, + + // level 4 - low quality + { + 20, 16, 25, 39, 50, 46, 62, 68, + 16, 18, 23, 38, 38, 53, 65, 68, + 25, 23, 31, 38, 53, 65, 68, 68, + 39, 38, 38, 53, 65, 68, 68, 68, + 50, 38, 53, 65, 68, 68, 68, 68, + 46, 53, 65, 68, 68, 68, 68, 68, + 62, 65, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68 + } + + +}; + +const unsigned char qtbl_chrominance[4][64] = { + // level 1 - high quality + { + 9, 8, 9, 11, 14, 17, 19, 24, + 8, 10, 9, 11, 14, 13, 17, 22, + 9, 9, 13, 14, 13, 15, 23, 26, + 11, 11, 14, 14, 15, 20, 26, 33, + 14, 14, 13, 15, 20, 24, 33, 39, + 17, 13, 15, 20, 24, 32, 39, 39, + 19, 17, 23, 26, 33, 39, 39, 39, + 24, 22, 26, 33, 39, 39, 39, 39 + }, + + // level 2 + { + 13, 11, 13, 16, 20, 20, 29, 37, + 11, 14, 14, 14, 16, 20, 26, 32, + 13, 14, 15, 17, 20, 23, 35, 40, + 16, 14, 17, 21, 23, 30, 40, 50, + 20, 16, 20, 23, 30, 37, 50, 59, + 20, 20, 23, 30, 37, 48, 59, 59, + 29, 26, 35, 40, 50, 59, 59, 59, + 37, 32, 40, 50, 59, 59, 59, 59 + }, + + + // level 3 + { + 17, 15, 17, 21, 20, 26, 38, 48, + 15, 19, 18, 17, 20, 26, 35, 43, + 17, 18, 20, 22, 26, 30, 46, 53, + 21, 17, 22, 28, 30, 39, 53, 64, + 20, 20, 26, 30, 39, 48, 64, 64, + 26, 26, 30, 39, 48, 63, 64, 64, + 38, 35, 46, 53, 64, 64, 64, 64, + 48, 43, 53, 64, 64, 64, 64, 64 + + + }, + + // level 4 - low quality + { + 21, 25, 32, 38, 54, 68, 68, 68, + 25, 28, 24, 38, 54, 68, 68, 68, + 32, 24, 32, 43, 66, 68, 68, 68, + 38, 38, 43, 53, 68, 68, 68, 68, + 54, 54, 66, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 68, 68 + + } + +}; + +const unsigned char qtbl0[64] = { + 0x10, 0x0B, 0x0A, 0x10, 0x18, 0x28, 0x33, 0x3D, + 0x0C, 0x0C, 0x0E, 0x13, 0x1A, 0x3A, 0x3C, 0x37, + 0x0E, 0x0D, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38, + 0x0E, 0x11, 0x16, 0x1D, 0x33, 0x57, 0x50, 0x3E, + 0x12, 0x16, 0x25, 0x38, 0x44, 0x6D, 0x67, 0x4D, + 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5C, + 0x31, 0x40, 0x4E, 0x57, 0x67, 0x79, 0x78, 0x65, + 0x48, 0x5C, 0x5F, 0x62, 0x70, 0x64, 0x67, 0x63 +}; + +//Added Quantization Table +const unsigned char std_chrominance_quant_tbl_plus[64] = { + 0x11, 0x12, 0x18, 0x2F, 0x63, 0x63, 0x63, 0x63, + 0x12, 0x15, 0x1A, 0x42, 0x63, 0x63, 0x63, 0x63, + 0x18, 0x1A, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x2F, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 +}; + +//Quantization Table0 +unsigned char std_luminance_quant_tbl[64] = { + 1, 1, 2, 1, 1, 2, 2, 2, + 2, 3, 2, 2, 3, 3, 6, 4, + 3, 3, 3, 3, 7, 5, 8, 4, + 6, 8, 8, 10, 9, 8, 7, 11, + 8, 10, 14, 13, 11, 10, 10, 12, + 10, 8, 8, 11, 16, 12, 12, 13, + 15, 15, 15, 15, 9, 11, 16, 17, + 15, 14, 17, 13, 14, 14, 14, 1 +}; + +//Quantization Table1 +unsigned char std_chrominance_quant_tbl[64] = { + 4, 4, 4, 5, 4, 5, 9, 5, + 5, 9, 15, 10, 8, 10, 15, 26, + 19, 9, 9, 19, 26, 26, 26, 26, + 13, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26 +}; + +//Huffman Table +unsigned char hdctbl0[16] = {0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}; +unsigned char hdctblg0[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb}; + +unsigned char hactbl0[16] = {0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d}; +const unsigned char hactblg0[162] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +//Huffman Table0 +unsigned char len_dc_luminance[16] = { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +unsigned char val_dc_luminance[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + +unsigned char len_ac_luminance[16] = { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; +unsigned char val_ac_luminance[162] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +//Huffman Table1 +unsigned char len_dc_chrominance[16] = { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; +unsigned char val_dc_chrominance[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + +unsigned char len_ac_chrominance[16] = { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; +unsigned char val_ac_chrominance[162] = { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x81, 0x08, 0x14, 0x42, + 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, + 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, + 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, + 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, + 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, + 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9 +}; + +#endif diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_mem.c b/drivers/media/video/samsung/jpeg_v2/jpg_mem.c new file mode 100644 index 0000000..55ced19 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_mem.c @@ -0,0 +1,62 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg_mem.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Operation for Jpeg encoder/docoder with memory + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <asm/io.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <asm/uaccess.h> +#include <linux/types.h> + +#include "jpg_mem.h" +#include "jpg_misc.h" +#include "jpg_opr.h" + +/*---------------------------------------------------------------------------- +*Function: phy_to_vir_addr + +*Parameters: dwContext : +*Return Value: True/False +*Implementation Notes: memory mapping from physical addr to virtual addr +-----------------------------------------------------------------------------*/ +void *phy_to_vir_addr(UINT32 phy_addr, int mem_size) +{ + void *reserved_mem; + + reserved_mem = (void *)ioremap((unsigned long)phy_addr, (int)mem_size); + + if (reserved_mem == NULL) { + jpg_err("phyical to virtual memory mapping was failed!\r\n"); + return NULL; + } + + return reserved_mem; +} + +void *mem_move(void *dst, const void *src, unsigned int size) +{ + return memmove(dst, src, size); +} + +void *mem_alloc(unsigned int size) +{ + void *alloc_mem; + + alloc_mem = (void *)kmalloc((int)size, GFP_KERNEL); + + if (alloc_mem == NULL) { + jpg_err("memory allocation failed!\r\n"); + return NULL; + } + + return alloc_mem; +} diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_mem.h b/drivers/media/video/samsung/jpeg_v2/jpg_mem.h new file mode 100644 index 0000000..f72d694 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_mem.h @@ -0,0 +1,144 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg_mem.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Definition for Operation of Jpeg encoder/docoder with memory + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __JPG_MEM_H__ +#define __JPG_MEM_H__ + +#include "jpg_misc.h" + +#include <linux/version.h> +#include <plat/media.h> + +#define JPG_REG_BASE_ADDR (0xFB600000) + +#define jpg_data_base_addr (UINT32)s3c_get_media_memory_bank(S3C_MDEV_JPEG, 0) + +#define MAX_JPG_WIDTH 2560 +#define MAX_JPG_HEIGHT 1920 +#define MAX_JPG_RESOLUTION (MAX_JPG_WIDTH * MAX_JPG_HEIGHT) + +/* It assumes that JPG thumbnail is not used + * Set the resolution when you need to use */ +#define MAX_JPG_THUMBNAIL_WIDTH 0 +#define MAX_JPG_THUMBNAIL_HEIGHT 0 +#define MAX_JPG_THUMBNAIL_RESOLUTION (MAX_JPG_THUMBNAIL_WIDTH * MAX_JPG_THUMBNAIL_HEIGHT) + +/* It assumes that RGB data encoding is not used + * Set the resolution when you need to use */ +#define MAX_RGB_WIDTH 0 +#define MAX_RGB_HEIGHT 0 +#define MAX_RGB_RESOLUTION (MAX_RGB_WIDTH * MAX_RGB_HEIGHT) + +/*******************************************************************************/ +/* define JPG & image memory */ +/* memory area is 4k(PAGE_SIZE) aligned because of VirtualCopyEx() */ + +/* Below definitions assume that JPEG_V2 uses only decoding without thumbnail. + * Max jpeg size of camera input is 3M, and decoded output data is YUV422. + * To reduce unnecessary memory reservation, + * useless definitions are set to 0. */ +#define JPG_STREAM_BUF_SIZE 3*1024*1024 +#define JPG_STREAM_THUMB_BUF_SIZE 0 +#define JPG_FRAME_BUF_SIZE \ + ((MAX_JPG_RESOLUTION * 2) / PAGE_SIZE + 1) * PAGE_SIZE +#define JPG_FRAME_THUMB_BUF_SIZE 0 +#define JPG_RGB_BUF_SIZE 0 + +/* Use below definitions if you need to use encoding and thumbnail + * Begin of definitions +#define JPG_STREAM_BUF_SIZE \ + (MAX_JPG_RESOLUTION / PAGE_SIZE + 1) * PAGE_SIZE +#define JPG_STREAM_THUMB_BUF_SIZE \ + (MAX_JPG_THUMBNAIL_RESOLUTION / PAGE_SIZE + 1) * PAGE_SIZE +#define JPG_FRAME_BUF_SIZE \ + ((MAX_JPG_RESOLUTION * 3) / PAGE_SIZE + 1) * PAGE_SIZE +#define JPG_FRAME_THUMB_BUF_SIZE \ + ((MAX_JPG_THUMBNAIL_RESOLUTION * 3) / PAGE_SIZE + 1) * PAGE_SIZE +#define JPG_RGB_BUF_SIZE \ + ((MAX_RGB_RESOLUTION * 4) / PAGE_SIZE + 1) * PAGE_SIZE +end of definitions */ + + +#define JPG_TOTAL_BUF_SIZE (JPG_STREAM_BUF_SIZE + \ + JPG_STREAM_THUMB_BUF_SIZE + \ + JPG_FRAME_BUF_SIZE + \ + JPG_FRAME_THUMB_BUF_SIZE + \ + JPG_RGB_BUF_SIZE) + +#define JPG_MAIN_STRART 0x00 +#define JPG_THUMB_START JPG_STREAM_BUF_SIZE +#define IMG_MAIN_START (JPG_STREAM_BUF_SIZE + JPG_STREAM_THUMB_BUF_SIZE) +#define IMG_THUMB_START (IMG_MAIN_START + JPG_FRAME_BUF_SIZE) + +/*******************************************************************************/ +#define COEF1_RGB_2_YUV 0x4d971e +#define COEF2_RGB_2_YUV 0x2c5783 +#define COEF3_RGB_2_YUV 0x836e13 + +/* + * JPEG HW Register Macro Definition + */ +#define JPG_1BIT_MASK 1 +#define JPG_4BIT_MASK 0xF + +/* SubSampling_Mode Mask is JPGMOD Register [2:0] bits mask */ +#define JPG_SMPL_MODE_MASK 0x07 + +/* Restart Interval value in JPGDRI Register is 2*/ +#define JPG_RESTART_INTRAVEL 2 + +/* HCLK_JPEG is CLK_GATE_D1_1 Register 5th bit */ +#define JPG_HCLK_JPEG_BIT 5 +/* SubSampling_Mode is JPGMOD Register 0th bit */ +#define JPG_SMPL_MODE_BIT 0 +/* Quantization Table #1 is JPGQHNO Register 8th bit */ +#define JPG_QUANT_TABLE1_BIT 8 +/* Quantization Table #2 is JPGQHNO Register 10th bit */ +#define JPG_QUANT_TABLE2_BIT 10 +/* Quantization Table #3 is JPGQHNO Register 12th bit */ +#define JPG_QUANT_TABLE3_BIT 12 +/* Mode Sel is JPGCMOD Register 5th bit */ +#define JPG_MODE_SEL_BIT 5 + +#define JPG_DECODE (0x1 << 3) +#define JPG_ENCODE (0x0 << 3) + +#define JPG_RESERVE_ZERO (0b000 << 2) + +#define ENABLE_MOTION_ENC (0x1<<3) +#define DISABLE_MOTION_ENC (0x0<<3) + +#define ENABLE_MOTION_DEC (0x1<<0) +#define DISABLE_MOTION_DEC (0x0<<0) + +#define ENABLE_HW_DEC (0x1<<2) +#define DISABLE_HW_DEC (0x0<<2) + +#define INCREMENTAL_DEC (0x1<<3) +#define NORMAL_DEC (0x0<<3) +#define YCBCR_MEMORY (0x1<<5) + +#define ENABLE_IRQ (0xf<<3) + +typedef struct __s5pc100_jpg_ctx { + volatile UINT32 jpg_data_addr; + volatile UINT32 img_data_addr; + volatile UINT32 jpg_thumb_data_addr; + volatile UINT32 img_thumb_data_addr; + int caller_process; +} sspc100_jpg_ctx; + +void *phy_to_vir_addr(UINT32 phy_addr, int mem_size); +void *mem_move(void *dst, const void *src, unsigned int size); +void *mem_alloc(unsigned int size); +#endif + diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_misc.c b/drivers/media/video/samsung/jpeg_v2/jpg_misc.c new file mode 100644 index 0000000..85c8f34 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_misc.c @@ -0,0 +1,80 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg_misc.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Operation for Jpeg encoder/docoder with mutex + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <stdarg.h> +#include <linux/kernel.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> + +#include <linux/version.h> + +#include <asm/io.h> +#include <linux/interrupt.h> +#include <linux/wait.h> + +#include "jpg_misc.h" +#include "jpg_mem.h" + +static HANDLE h_mutex = NULL; + +/*---------------------------------------------------------------------------- +*Function: create_jpg_mutex +*Implementation Notes: Create Mutex handle +-----------------------------------------------------------------------------*/ +HANDLE create_jpg_mutex(void) +{ + h_mutex = (HANDLE)kmalloc(sizeof(struct mutex), GFP_KERNEL); + + if (h_mutex == NULL) + return NULL; + + mutex_init(h_mutex); + + return h_mutex; +} + +/*---------------------------------------------------------------------------- +*Function: lock_jpg_mutex +*Implementation Notes: lock mutex +-----------------------------------------------------------------------------*/ +DWORD lock_jpg_mutex(void) +{ + mutex_lock(h_mutex); + return 1; +} + +/*---------------------------------------------------------------------------- +*Function: unlock_jpg_mutex +*Implementation Notes: unlock mutex +-----------------------------------------------------------------------------*/ +DWORD unlock_jpg_mutex(void) +{ + mutex_unlock(h_mutex); + + return 1; +} + +/*---------------------------------------------------------------------------- +*Function: delete_jpg_mutex +*Implementation Notes: delete mutex handle +-----------------------------------------------------------------------------*/ +void delete_jpg_mutex(void) +{ + if (h_mutex == NULL) + return; + + mutex_destroy(h_mutex); +} + diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_misc.h b/drivers/media/video/samsung/jpeg_v2/jpg_misc.h new file mode 100644 index 0000000..8581f55 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_misc.h @@ -0,0 +1,34 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg_misc.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Definition for Operation of Jpeg encoder/docoder with mutex + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __JPG_MISC_H__ +#define __JPG_MISC_H__ + +#include <linux/types.h> + +typedef unsigned char UCHAR; +typedef unsigned long ULONG; +typedef unsigned int UINT; +typedef struct mutex * HANDLE; +typedef unsigned long DWORD; +typedef unsigned int UINT32; +typedef unsigned char UINT8; +typedef enum {FALSE, TRUE} BOOL; + +#define INT_TIMEOUT 1000 + +HANDLE create_jpg_mutex(void); +DWORD lock_jpg_mutex(void); +DWORD unlock_jpg_mutex(void); +void delete_jpg_mutex(void); + +#endif diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_opr.c b/drivers/media/video/samsung/jpeg_v2/jpg_opr.c new file mode 100644 index 0000000..a512c80 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_opr.c @@ -0,0 +1,310 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg_opr.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Operation for Jpeg encoder/docoder + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/delay.h> +#include <asm/io.h> + +#include "jpg_mem.h" +#include "jpg_misc.h" +#include "jpg_opr.h" +#include "jpg_conf.h" + +#include "regs-jpeg.h" + +extern void __iomem *s3c_jpeg_base; +extern int jpg_irq_reason; + +enum { + UNKNOWN, + BASELINE = 0xC0, + EXTENDED_SEQ = 0xC1, + PROGRESSIVE = 0xC2 +} jpg_sof_marker; + +jpg_return_status wait_for_interrupt(void) +{ + if (interruptible_sleep_on_timeout(&wait_queue_jpeg, INT_TIMEOUT) == 0) { + jpg_err("waiting for interrupt is timeout\n"); + } + + return jpg_irq_reason; +} + +jpg_return_status decode_jpg(sspc100_jpg_ctx *jpg_ctx, + jpg_dec_proc_param *dec_param) +{ + volatile int ret; + sample_mode_t sample_mode; + UINT32 width, height; + jpg_dbg("enter decode_jpg function\n"); + + if (jpg_ctx) + reset_jpg(jpg_ctx); + else { + jpg_err("jpg ctx is NULL\n"); + return JPG_FAIL; + } + +/* set jpeg clock register : power on */ + writel(readl(s3c_jpeg_base + S3C_JPEG_CLKCON_REG) | + (S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE), + s3c_jpeg_base + S3C_JPEG_CLKCON_REG); + /* set jpeg mod register : decode */ + writel(readl(s3c_jpeg_base + S3C_JPEG_MOD_REG) | + (S3C_JPEG_MOD_REG_PROC_DEC), + s3c_jpeg_base + S3C_JPEG_MOD_REG); + /* set jpeg interrupt setting register */ + writel(readl(s3c_jpeg_base + S3C_JPEG_INTSE_REG) | + (S3C_JPEG_INTSE_REG_RSTM_INT_EN | + S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN | + S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN), + s3c_jpeg_base + S3C_JPEG_INTSE_REG); + /* set jpeg deocde ouput format register */ + writel(readl(s3c_jpeg_base + S3C_JPEG_OUTFORM_REG) & + ~(S3C_JPEG_OUTFORM_REG_YCBCY420), + s3c_jpeg_base + S3C_JPEG_OUTFORM_REG); + writel(readl(s3c_jpeg_base + S3C_JPEG_OUTFORM_REG) | + (dec_param->out_format << 0), + s3c_jpeg_base + S3C_JPEG_OUTFORM_REG); + + /* set the address of compressed input data */ + writel(jpg_ctx->img_data_addr, s3c_jpeg_base + S3C_JPEG_IMGADR_REG); + + /* set the address of decompressed image */ + writel(jpg_ctx->jpg_data_addr, s3c_jpeg_base + S3C_JPEG_JPGADR_REG); + + /* start decoding */ + writel(readl(s3c_jpeg_base + S3C_JPEG_JRSTART_REG) | + S3C_JPEG_JRSTART_REG_ENABLE, + s3c_jpeg_base + S3C_JPEG_JSTART_REG); + + ret = wait_for_interrupt(); + + if (ret != OK_ENC_OR_DEC) { + jpg_err("jpg decode error(%d)\n", ret); + return JPG_FAIL; + } + + sample_mode = get_sample_type(jpg_ctx); + jpg_dbg("sample_mode : %d\n", sample_mode); + + if (sample_mode == JPG_SAMPLE_UNKNOWN) { + jpg_err("jpg has invalid sample_mode\r\n"); + return JPG_FAIL; + } + + dec_param->sample_mode = sample_mode; + + get_xy(jpg_ctx, &width, &height); + jpg_dbg("decode size:: width : %d height : %d\n", width, height); + + dec_param->data_size = get_yuv_size(dec_param->out_format, width, height); + dec_param->width = width; + dec_param->height = height; + + return JPG_SUCCESS; +} + +void reset_jpg(sspc100_jpg_ctx *jpg_ctx) +{ +jpg_dbg("s3c_jpeg_base %p \n", s3c_jpeg_base); + writel(S3C_JPEG_SW_RESET_REG_ENABLE, + s3c_jpeg_base + S3C_JPEG_SW_RESET_REG); + + do { + writel(S3C_JPEG_SW_RESET_REG_ENABLE, + s3c_jpeg_base + S3C_JPEG_SW_RESET_REG); + } while (((readl(s3c_jpeg_base + S3C_JPEG_SW_RESET_REG)) + & S3C_JPEG_SW_RESET_REG_ENABLE) == S3C_JPEG_SW_RESET_REG_ENABLE); +} + +sample_mode_t get_sample_type(sspc100_jpg_ctx *jpg_ctx) +{ + ULONG jpgMode; + sample_mode_t sample_mode = JPG_SAMPLE_UNKNOWN; + + jpgMode = readl(s3c_jpeg_base + S3C_JPEG_MOD_REG); + + sample_mode = + ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_444) ? JPG_444 : + ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_422) ? JPG_422 : + ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_420) ? JPG_420 : + ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_400) ? JPG_400 : + ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_411) ? JPG_411 : JPG_SAMPLE_UNKNOWN; + + return(sample_mode); +} + +void get_xy(sspc100_jpg_ctx *jpg_ctx, UINT32 *x, UINT32 *y) +{ + *x = (readl(s3c_jpeg_base + S3C_JPEG_X_U_REG)<<8)| + readl(s3c_jpeg_base + S3C_JPEG_X_L_REG); + *y = (readl(s3c_jpeg_base + S3C_JPEG_Y_U_REG)<<8)| + readl(s3c_jpeg_base + S3C_JPEG_Y_L_REG); +} + +UINT32 get_yuv_size(out_mode_t out_format, UINT32 width, UINT32 height) +{ + switch (out_format) { + case YCBCR_422 : + + if (width % 16 != 0) + width += 16 - (width % 16); + + if (height % 8 != 0) + height += 8 - (height % 8); + + break; + + case YCBCR_420 : + + if (width % 16 != 0) + width += 16 - (width % 16); + + if (height % 16 != 0) + height += 16 - (height % 16); + + break; + + case YCBCR_SAMPLE_UNKNOWN: + break; + } + + jpg_dbg("get_yuv_size width(%d) height(%d)\n", width, height); + + switch (out_format) { + case YCBCR_422 : + return(width*height*2); + case YCBCR_420 : + return((width*height) + (width*height >> 1)); + default : + return(0); + } +} + +jpg_return_status encode_jpg(sspc100_jpg_ctx *jpg_ctx, + jpg_enc_proc_param *enc_param) +{ + + UINT i, ret; + UINT32 cmd_val; + + if (enc_param->width <= 0 || enc_param->width > MAX_JPG_WIDTH + || enc_param->height <= 0 || enc_param->height > MAX_JPG_HEIGHT) { + jpg_err("::encoder : width: %d, height: %d \n", + enc_param->width, enc_param->height); + jpg_err("::encoder : invalid width/height \n"); + return JPG_FAIL; + } + +/* SW reset */ + if (jpg_ctx) + reset_jpg(jpg_ctx); + else { + jpg_err("::jpg ctx is NULL\n"); + return JPG_FAIL; + } + /* set jpeg clock register : power on */ + writel(readl(s3c_jpeg_base + S3C_JPEG_CLKCON_REG) | + (S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE), + s3c_jpeg_base + S3C_JPEG_CLKCON_REG); + /* set jpeg mod register : encode */ + writel(readl(s3c_jpeg_base + S3C_JPEG_CMOD_REG) | + (enc_param->in_format << JPG_MODE_SEL_BIT), + s3c_jpeg_base + S3C_JPEG_CMOD_REG); + cmd_val = (enc_param->sample_mode == JPG_422) ? + (S3C_JPEG_MOD_REG_SUBSAMPLE_422) : (S3C_JPEG_MOD_REG_SUBSAMPLE_420); + + writel(cmd_val | S3C_JPEG_MOD_REG_PROC_ENC, s3c_jpeg_base + S3C_JPEG_MOD_REG); + + /* set DRI(Define Restart Interval) */ + writel(JPG_RESTART_INTRAVEL, s3c_jpeg_base + S3C_JPEG_DRI_L_REG); + writel((JPG_RESTART_INTRAVEL>>8), s3c_jpeg_base + S3C_JPEG_DRI_U_REG); + + writel(S3C_JPEG_QHTBL_REG_QT_NUM1, s3c_jpeg_base + S3C_JPEG_QTBL_REG); + writel(0x00, s3c_jpeg_base + S3C_JPEG_HTBL_REG); + + /* Horizontal resolution */ + writel((enc_param->width>>8), s3c_jpeg_base + S3C_JPEG_X_U_REG); + writel(enc_param->width, s3c_jpeg_base + S3C_JPEG_X_L_REG); + + /* Vertical resolution */ + writel((enc_param->height>>8), s3c_jpeg_base + S3C_JPEG_Y_U_REG); + writel(enc_param->height, s3c_jpeg_base + S3C_JPEG_Y_L_REG); + + jpg_dbg("enc_param->enc_type : %d\n", enc_param->enc_type); + + if (enc_param->enc_type == JPG_MAIN) { + jpg_dbg("encode image size width: %d, height: %d\n", + enc_param->width, enc_param->height); + writel(jpg_ctx->img_data_addr, s3c_jpeg_base + S3C_JPEG_IMGADR_REG); + writel(jpg_ctx->jpg_data_addr, s3c_jpeg_base + S3C_JPEG_JPGADR_REG); + } else { // thumbnail encoding + jpg_dbg("thumb image size width: %d, height: %d\n", + enc_param->width, enc_param->height); + writel(jpg_ctx->img_thumb_data_addr, s3c_jpeg_base + S3C_JPEG_IMGADR_REG); + writel(jpg_ctx->jpg_thumb_data_addr, s3c_jpeg_base + S3C_JPEG_JPGADR_REG); + } + + /* Coefficient value 1~3 for RGB to YCbCr */ + writel(COEF1_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF1_REG); + writel(COEF2_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF2_REG); + writel(COEF3_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF3_REG); + + /* Quantiazation and Huffman Table setting */ + for (i = 0; i < 64; i++) { + writel((UINT32)qtbl_luminance[enc_param->quality][i], + s3c_jpeg_base + S3C_JPEG_QTBL0_REG + (i*0x04)); + } + for (i = 0; i < 64; i++) { + writel((UINT32)qtbl_chrominance[enc_param->quality][i], + s3c_jpeg_base + S3C_JPEG_QTBL1_REG + (i*0x04)); + } + for (i = 0; i < 16; i++) { + writel((UINT32)hdctbl0[i], + s3c_jpeg_base + S3C_JPEG_HDCTBL0_REG + (i*0x04)); + } + for (i = 0; i < 12; i++) { + writel((UINT32)hdctblg0[i], + s3c_jpeg_base + S3C_JPEG_HDCTBLG0_REG + (i*0x04)); + } + for (i = 0; i < 16; i++) { + writel((UINT32)hactbl0[i], + s3c_jpeg_base + S3C_JPEG_HACTBL0_REG + (i*0x04)); + } + for (i = 0; i < 162; i++) { + writel((UINT32)hactblg0[i], + s3c_jpeg_base + S3C_JPEG_HACTBLG0_REG + (i*0x04)); + } + writel(readl(s3c_jpeg_base + S3C_JPEG_INTSE_REG) | + (S3C_JPEG_INTSE_REG_RSTM_INT_EN | + S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN | + S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN), + s3c_jpeg_base + S3C_JPEG_INTSE_REG); + + writel(readl(s3c_jpeg_base + S3C_JPEG_JSTART_REG) | + S3C_JPEG_JSTART_REG_ENABLE, + s3c_jpeg_base + S3C_JPEG_JSTART_REG); + ret = wait_for_interrupt(); + + if (ret != OK_ENC_OR_DEC) { + jpg_err("jpeg encoding error(%d)\n", ret); + return JPG_FAIL; + } + + enc_param->file_size = readl(s3c_jpeg_base + S3C_JPEG_CNT_U_REG) << 16; + enc_param->file_size |= readl(s3c_jpeg_base + S3C_JPEG_CNT_M_REG) << 8; + enc_param->file_size |= readl(s3c_jpeg_base + S3C_JPEG_CNT_L_REG); + + return JPG_SUCCESS; + +} diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_opr.h b/drivers/media/video/samsung/jpeg_v2/jpg_opr.h new file mode 100644 index 0000000..5ad142c --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/jpg_opr.h @@ -0,0 +1,153 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/jpg_opr.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Definition for Operation of Jpeg encoder/docoder + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __JPG_OPR_H__ +#define __JPG_OPR_H__ + +#include <linux/interrupt.h> + + +/* debug macro */ +#define JPG_DEBUG(fmt, ...) \ + do { \ + printk(KERN_DEBUG \ + "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while(0) + + +#define JPG_WARN(fmt, ...) \ + do { \ + printk(KERN_WARNING \ + fmt, ##__VA_ARGS__); \ + } while (0) + + + +#define JPG_ERROR(fmt, ...) \ + do { \ + printk(KERN_ERR \ + "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) + + + +#ifdef CONFIG_VIDEO_JPEG_DEBUG +#define jpg_dbg(fmt, ...) JPG_DEBUG(fmt, ##__VA_ARGS__) +#else +#define jpg_dbg(fmt, ...) +#endif + +#define jpg_warn(fmt, ...) JPG_WARN(fmt, ##__VA_ARGS__) +#define jpg_err(fmt, ...) JPG_ERROR(fmt, ##__VA_ARGS__) + +extern wait_queue_head_t wait_queue_jpeg; + +typedef enum { + JPG_FAIL, + JPG_SUCCESS, + OK_HD_PARSING, + ERR_HD_PARSING, + OK_ENC_OR_DEC, + ERR_ENC_OR_DEC, + ERR_UNKNOWN +} jpg_return_status; + +typedef enum { + JPG_RGB16, + JPG_YCBYCR, + JPG_TYPE_UNKNOWN +} image_type_t; + +typedef enum { + JPG_444, + JPG_422, + JPG_420, + JPG_400, + RESERVED1, + RESERVED2, + JPG_411, + JPG_SAMPLE_UNKNOWN +} sample_mode_t; + +typedef enum { + YCBCR_422, + YCBCR_420, + YCBCR_SAMPLE_UNKNOWN +} out_mode_t; + +typedef enum { + JPG_MODESEL_YCBCR = 1, + JPG_MODESEL_RGB, + JPG_MODESEL_UNKNOWN +} in_mode_t; + +typedef enum { + JPG_MAIN, + JPG_THUMBNAIL +} encode_type_t; + +typedef enum { + JPG_QUALITY_LEVEL_1 = 0, /*high quality*/ + JPG_QUALITY_LEVEL_2, + JPG_QUALITY_LEVEL_3, + JPG_QUALITY_LEVEL_4 /*low quality*/ +} image_quality_type_t; + +typedef struct { + sample_mode_t sample_mode; + encode_type_t dec_type; + out_mode_t out_format; + UINT32 width; + UINT32 height; + UINT32 data_size; + UINT32 file_size; +} jpg_dec_proc_param; + +typedef struct { + sample_mode_t sample_mode; + encode_type_t enc_type; + in_mode_t in_format; + image_quality_type_t quality; + UINT32 width; + UINT32 height; + UINT32 data_size; + UINT32 file_size; +} jpg_enc_proc_param; + +typedef struct { + char *in_buf; + char *phy_in_buf; + int in_buf_size; + char *out_buf; + char *phy_out_buf; + int out_buf_size; + char *in_thumb_buf; + char *phy_in_thumb_buf; + int in_thumb_buf_size; + char *out_thumb_buf; + char *phy_out_thumb_buf; + int out_thumb_buf_size; + char *mapped_addr; + jpg_dec_proc_param *dec_param; + jpg_enc_proc_param *enc_param; + jpg_enc_proc_param *thumb_enc_param; +} jpg_args; + +void reset_jpg(sspc100_jpg_ctx *jpg_ctx); +jpg_return_status decode_jpg(sspc100_jpg_ctx *jpg_ctx, jpg_dec_proc_param *dec_param); +jpg_return_status encode_jpg(sspc100_jpg_ctx *jpg_ctx, jpg_enc_proc_param *enc_param); +jpg_return_status wait_for_interrupt(void); +sample_mode_t get_sample_type(sspc100_jpg_ctx *jpg_ctx); +void get_xy(sspc100_jpg_ctx *jpg_ctx, UINT32 *x, UINT32 *y); +UINT32 get_yuv_size(out_mode_t out_format, UINT32 width, UINT32 height); + +#endif diff --git a/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h b/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h new file mode 100644 index 0000000..e156e7b --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h @@ -0,0 +1,147 @@ +/* linux/drivers/media/video/samsung/jpeg/regs-jpeg.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Register definition file for Samsung JPEG Encoder/Decoder + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARM_REGS_S3C_JPEG_H +#define __ASM_ARM_REGS_S3C_JPEG_H + +/*************************************************************************/ +/*JPEG Registers part */ +/*************************************************************************/ +#define S3C_JPEG_REG(x) ((x)) + +/* JPEG Codec Control Registers */ + +#define S3C_JPEG_MOD_REG S3C_JPEG_REG(0x00) /* Sub-sampling Mode Register */ +#define S3C_JPEG_OPR_REG S3C_JPEG_REG(0x04) /* Operation Status Register */ +#define S3C_JPEG_QTBL_REG S3C_JPEG_REG(0x08) /* Quantization Table Number Register and Huffman Table Number Register */ +#define S3C_JPEG_HTBL_REG S3C_JPEG_REG(0x0c) /* Huffman Table Number Register */ +#define S3C_JPEG_DRI_U_REG S3C_JPEG_REG(0x10) /* MCU, which inserts RST marker(upper 8bit) */ +#define S3C_JPEG_DRI_L_REG S3C_JPEG_REG(0x14) /* MCU, which inserts RST marker(lower 8bit) */ +#define S3C_JPEG_Y_U_REG S3C_JPEG_REG(0x18) /* Vertical Resolution (upper 8bit) */ +#define S3C_JPEG_Y_L_REG S3C_JPEG_REG(0x1c) /* Vertical Resolution (lower 8bit) */ +#define S3C_JPEG_X_U_REG S3C_JPEG_REG(0x20) /* Horizontal Resolution (upper 8bit) */ +#define S3C_JPEG_X_L_REG S3C_JPEG_REG(0x24) /* Horizontal Resolution (lower 8bit) */ +#define S3C_JPEG_CNT_U_REG S3C_JPEG_REG(0x28) /* The amount of the compressed data in bytes (upper 8bit) */ +#define S3C_JPEG_CNT_M_REG S3C_JPEG_REG(0x2c) /* The amount of the compressed data in bytes (middle 8bit) */ +#define S3C_JPEG_CNT_L_REG S3C_JPEG_REG(0x30) /* The amount of the compressed data in bytes (lowerz 8bit) */ +#define S3C_JPEG_INTSE_REG S3C_JPEG_REG(0x34) /* Interrupt setting register */ +#define S3C_JPEG_INTST_REG S3C_JPEG_REG(0x38) /* Interrupt status */ + +#define S3C_JPEG_COM_REG S3C_JPEG_REG(0x4c) /* Command register */ + +#define S3C_JPEG_IMGADR_REG S3C_JPEG_REG(0x50) /* Source or destination image addresss */ + +#define S3C_JPEG_JPGADR_REG S3C_JPEG_REG(0x58) /* Source or destination JPEG file address */ +#define S3C_JPEG_COEF1_REG S3C_JPEG_REG(0x5c) /* Coefficient values for RGB <-> YCbCr converter */ +#define S3C_JPEG_COEF2_REG S3C_JPEG_REG(0x60) /* Coefficient values for RGB <-> YCbCr converter */ +#define S3C_JPEG_COEF3_REG S3C_JPEG_REG(0x64) /* Coefficient values for RGB <-> YCbCr converter */ + +#define S3C_JPEG_CMOD_REG S3C_JPEG_REG(0x68) /* Mode selection and core clock setting */ +#define S3C_JPEG_CLKCON_REG S3C_JPEG_REG(0x6c) /* Power on/off and clock down control */ + +#define S3C_JPEG_JSTART_REG S3C_JPEG_REG(0x70) /* Start compression or decompression */ +#define S3C_JPEG_JRSTART_REG S3C_JPEG_REG(0x74) /* Restart decompression after header analysis */ +#define S3C_JPEG_SW_RESET_REG S3C_JPEG_REG(0x78) /* S/W reset */ + +#define S3C_JPEG_TIMER_SE_REG S3C_JPEG_REG(0x7c) /* Internal timer setting register */ +#define S3C_JPEG_TIMER_ST_REG S3C_JPEG_REG(0x80) /* Internal timer status register */ +#define S3C_JPEG_COMSTAT_REG S3C_JPEG_REG(0x84) /* Command status register */ +#define S3C_JPEG_OUTFORM_REG S3C_JPEG_REG(0x88) /* Output color format of decompression */ +#define S3C_JPEG_VERSION_REG S3C_JPEG_REG(0x8c) /* Version register */ + +#define S3C_JPEG_ENC_STREAM_INTSE_REG S3C_JPEG_REG(0x98) /* Compressed stream size interrupt setting register */ +#define S3C_JPEG_ENC_STREAM_INTST_REG S3C_JPEG_REG(0x9c) /* Compressed stream size interrupt status register */ + +#define S3C_JPEG_QTBL0_REG S3C_JPEG_REG(0x400) /* Quantization table 0 */ +#define S3C_JPEG_QTBL1_REG S3C_JPEG_REG(0x500) /* Quantization table 1 */ +#define S3C_JPEG_QTBL2_REG S3C_JPEG_REG(0x600) /* Quantization table 2 */ +#define S3C_JPEG_QTBL3_REG S3C_JPEG_REG(0x700) /* Quantization table 3 */ + +#define S3C_JPEG_HDCTBL0_REG S3C_JPEG_REG(0x800) /* DC huffman table 0 */ +#define S3C_JPEG_HDCTBLG0_REG S3C_JPEG_REG(0x840) /* DC huffman table group 0 */ +#define S3C_JPEG_HACTBL0_REG S3C_JPEG_REG(0x880) /* AC huffman table 0 */ +#define S3C_JPEG_HACTBLG0_REG S3C_JPEG_REG(0x8c0) /* AC huffman table group 0 */ +#define S3C_JPEG_HDCTBL1_REG S3C_JPEG_REG(0xc00) /* DC huffman table 1 */ +#define S3C_JPEG_HDCTBLG1_REG S3C_JPEG_REG(0xc40) /* DC huffman table group 1 */ +#define S3C_JPEG_HACTBL1_REG S3C_JPEG_REG(0xc80) /* AC huffman table 1 */ +#define S3C_JPEG_HACTBLG1_REG S3C_JPEG_REG(0xcc0) /* AC huffman table group 1 */ + +/*************************************************************************/ +/* Bit definition part */ +/*************************************************************************/ + +/* JPEG Mode Register bit */ +#define S3C_JPEG_MOD_REG_PROC_ENC (0<<3) +#define S3C_JPEG_MOD_REG_PROC_DEC (1<<3) + +#define S3C_JPEG_MOD_REG_SUBSAMPLE_444 (0<<0) +#define S3C_JPEG_MOD_REG_SUBSAMPLE_422 (1<<0) +#define S3C_JPEG_MOD_REG_SUBSAMPLE_420 (2<<0) +#define S3C_JPEG_MOD_REG_SUBSAMPLE_GRAY (3<<0) + +/* JPEG Operation Status Register bit */ +#define S3C_JPEG_OPR_REG_OPERATE (1<<0) +#define S3C_JPEG_OPR_REG_NO_OPERATE (0<<0) + +/* Quantization Table And Huffman Table Number Register bit */ +#define S3C_JPEG_QHTBL_REG_QT_NUM4 (1<<6) +#define S3C_JPEG_QHTBL_REG_QT_NUM3 (1<<4) +#define S3C_JPEG_QHTBL_REG_QT_NUM2 (1<<2) +#define S3C_JPEG_QHTBL_REG_QT_NUM1 (1<<0) + +#define S3C_JPEG_QHTBL_REG_HT_NUM4_AC (1<<7) +#define S3C_JPEG_QHTBL_REG_HT_NUM4_DC (1<<6) +#define S3C_JPEG_QHTBL_REG_HT_NUM3_AC (1<<5) +#define S3C_JPEG_QHTBL_REG_HT_NUM3_DC (1<<4) +#define S3C_JPEG_QHTBL_REG_HT_NUM2_AC (1<<3) +#define S3C_JPEG_QHTBL_REG_HT_NUM2_DC (1<<2) +#define S3C_JPEG_QHTBL_REG_HT_NUM1_AC (1<<1) +#define S3C_JPEG_QHTBL_REG_HT_NUM1_DC (1<<0) + + +/* JPEG Color Mode Register bit */ +#define S3C_JPEG_CMOD_REG_MOD_SEL_RGB (2<<5) +#define S3C_JPEG_CMOD_REG_MOD_SEL_YCBCR422 (1<<5) +#define S3C_JPEG_CMOD_REG_MOD_MODE_Y16 (1<<1) +#define S3C_JPEG_CMOD_REG_MOD_MODE_0 (0<<1) + +/* JPEG Clock Control Register bit */ +#define S3C_JPEG_CLKCON_REG_CLK_DOWN_READY_ENABLE (0<<1) +#define S3C_JPEG_CLKCON_REG_CLK_DOWN_READY_DISABLE (1<<1) +#define S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE (1<<0) +#define S3C_JPEG_CLKCON_REG_POWER_ON_DISABLE (0<<0) + +/* JPEG Start Register bit */ +#define S3C_JPEG_JSTART_REG_ENABLE (1<<0) + +/* JPEG Rdstart Register bit */ +#define S3C_JPEG_JRSTART_REG_ENABLE (1<<0) + +/* JPEG SW Reset Register bit */ +#define S3C_JPEG_SW_RESET_REG_ENABLE (1<<0) + +/* JPEG Interrupt Setting Register bit */ +#define S3C_JPEG_INTSE_REG_RSTM_INT_EN (1<<7) +#define S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN (1<<6) +#define S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN (1<<5) + +/* JPEG Decompression Output Format Register bit */ +#define S3C_JPEG_OUTFORM_REG_YCBCY422 (0<<0) +#define S3C_JPEG_OUTFORM_REG_YCBCY420 (1<<0) + +/* JPEG Decompression Input Stream Size Register bit */ +#define S3C_JPEG_DEC_STREAM_SIZE_REG_PROHIBIT (0x1FFFFFFF<<0) + +/* JPEG Command Register bit */ +#define S3C_JPEG_COM_INT_RELEASE (1<<2) + +#endif //__ASM_ARM_REGS_S3C_JPEG_H diff --git a/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c new file mode 100644 index 0000000..bca4834 --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c @@ -0,0 +1,536 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Core file for Samsung Jpeg Interface driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/major.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <linux/signal.h> +#include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/kmod.h> +#include <linux/vmalloc.h> +#include <linux/init.h> +#include <asm/io.h> +#include <asm/page.h> +#include <mach/irqs.h> +#include <linux/semaphore.h> +#include <mach/map.h> +#include <mach/pd.h> +#include <linux/miscdevice.h> +#include <linux/vmalloc.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/platform_device.h> + +#include <linux/version.h> +#include <plat/media.h> + +#include <linux/time.h> +#include <linux/clk.h> + +#include "s3c-jpeg.h" +#include "jpg_mem.h" +#include "jpg_misc.h" +#include "jpg_opr.h" +#include "regs-jpeg.h" + +static struct clk *s3c_jpeg_clk; + +static struct resource *s3c_jpeg_mem; +void __iomem *s3c_jpeg_base; +static int irq_no; +static int instanceNo = 0; +volatile int jpg_irq_reason; +wait_queue_head_t wait_queue_jpeg; + + +DECLARE_WAIT_QUEUE_HEAD(WaitQueue_JPEG); +irqreturn_t s3c_jpeg_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int int_status; + unsigned int status; + + jpg_dbg("=====enter s3c_jpeg_irq===== \r\n"); + + int_status = readl(s3c_jpeg_base + S3C_JPEG_INTST_REG); + + do{ + status = readl(s3c_jpeg_base + S3C_JPEG_OPR_REG); + }while(status); + + writel(S3C_JPEG_COM_INT_RELEASE, s3c_jpeg_base + S3C_JPEG_COM_REG); + jpg_dbg("int_status : 0x%08x status : 0x%08x\n", int_status, status); + + if (int_status) { + switch (int_status) { + case 0x40 : + jpg_irq_reason = OK_ENC_OR_DEC; + break; + case 0x20 : + jpg_irq_reason = ERR_ENC_OR_DEC; + break; + default : + jpg_irq_reason = ERR_UNKNOWN; + } + + wake_up_interruptible(&wait_queue_jpeg); + } else { + jpg_irq_reason = ERR_UNKNOWN; + wake_up_interruptible(&wait_queue_jpeg); + } + + return IRQ_HANDLED; +} +static int s3c_jpeg_open(struct inode *inode, struct file *file) +{ + sspc100_jpg_ctx *jpg_reg_ctx; + DWORD ret; + + ret = s5pv210_pd_enable("jpeg_pd"); + if (ret < 0) { + jpg_err("failed to enable jpeg power domain\n"); + return FALSE; + } + + /* clock enable */ + clk_enable(s3c_jpeg_clk); + + jpg_dbg("JPG_open \r\n"); + + jpg_reg_ctx = (sspc100_jpg_ctx *)mem_alloc(sizeof(sspc100_jpg_ctx)); + memset(jpg_reg_ctx, 0x00, sizeof(sspc100_jpg_ctx)); + + ret = lock_jpg_mutex(); + + if (!ret) { + jpg_err("JPG Mutex Lock Fail\r\n"); + unlock_jpg_mutex(); + kfree(jpg_reg_ctx); + return FALSE; + } + + if (instanceNo > MAX_INSTANCE_NUM) { + jpg_err("Instance Number error-JPEG is running, \ + instance number is %d\n", instanceNo); + unlock_jpg_mutex(); + kfree(jpg_reg_ctx); + return FALSE; + } + + instanceNo++; + + unlock_jpg_mutex(); + + file->private_data = (sspc100_jpg_ctx *)jpg_reg_ctx; + + return 0; +} + + +static int s3c_jpeg_release(struct inode *inode, struct file *file) +{ + DWORD ret; + sspc100_jpg_ctx *jpg_reg_ctx; + + jpg_dbg("JPG_Close\n"); + + jpg_reg_ctx = (sspc100_jpg_ctx *)file->private_data; + + if (!jpg_reg_ctx) { + jpg_err("JPG Invalid Input Handle\r\n"); + return FALSE; + } + + ret = lock_jpg_mutex(); + + if (!ret) { + jpg_err("JPG Mutex Lock Fail\r\n"); + return FALSE; + } + + if ((--instanceNo) < 0) + instanceNo = 0; + + unlock_jpg_mutex(); + kfree(jpg_reg_ctx); + +/* clock disable */ + clk_disable(s3c_jpeg_clk); + ret = s5pv210_pd_disable("jpeg_pd"); + if (ret < 0) { + jpg_err("failed to disable jpeg power domain\n"); + return FALSE; + } + + return 0; +} + + +static ssize_t s3c_jpeg_write(struct file *file, const char *buf, size_t count, loff_t *pos) +{ + return 0; +} + +static ssize_t s3c_jpeg_read(struct file *file, char *buf, size_t count, loff_t *pos) +{ + return 0; +} + +static int s3c_jpeg_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + static sspc100_jpg_ctx *jpg_reg_ctx; + jpg_args param; + BOOL result = TRUE; + DWORD ret; + int out; + + + jpg_reg_ctx = (sspc100_jpg_ctx *)file->private_data; + + if (!jpg_reg_ctx) { + jpg_err("JPG Invalid Input Handle\r\n"); + return FALSE; + } + + ret = lock_jpg_mutex(); + + if (!ret) { + jpg_err("JPG Mutex Lock Fail\r\n"); + return FALSE; + } + + switch (cmd) { + case IOCTL_JPG_DECODE: + + jpg_dbg("IOCTL_JPEG_DECODE\n"); + + out = copy_from_user(¶m, (jpg_args *)arg, sizeof(jpg_args)); + + jpg_reg_ctx->jpg_data_addr = (UINT32)jpg_data_base_addr; + jpg_reg_ctx->img_data_addr = (UINT32)jpg_data_base_addr + + JPG_STREAM_BUF_SIZE + + JPG_STREAM_THUMB_BUF_SIZE; + + result = decode_jpg(jpg_reg_ctx, param.dec_param); + out = copy_to_user((void *)arg, (void *) & param, sizeof(jpg_args)); + break; + + case IOCTL_JPG_ENCODE: + + jpg_dbg("IOCTL_JPEG_ENCODE\n"); + + out = copy_from_user(¶m, (jpg_args *)arg, sizeof(jpg_args)); + + jpg_dbg("encode size :: width : %d hegiht : %d\n", + param.enc_param->width, param.enc_param->height); + + if (param.enc_param->enc_type == JPG_MAIN) { + jpg_reg_ctx->jpg_data_addr = (UINT32)jpg_data_base_addr ; + jpg_reg_ctx->img_data_addr = (UINT32)jpg_data_base_addr + + JPG_STREAM_BUF_SIZE + + JPG_STREAM_THUMB_BUF_SIZE; + jpg_dbg("enc_img_data_addr=0x%08x, enc_jpg_data_addr=0x%08x\n" + , jpg_reg_ctx->img_data_addr,jpg_reg_ctx->jpg_data_addr); + + result = encode_jpg(jpg_reg_ctx, param.enc_param); + } else { + jpg_reg_ctx->img_thumb_data_addr = (UINT32)jpg_data_base_addr + + JPG_STREAM_BUF_SIZE + + JPG_STREAM_THUMB_BUF_SIZE + + JPG_FRAME_BUF_SIZE; + jpg_reg_ctx->jpg_thumb_data_addr = (UINT32)jpg_data_base_addr + + JPG_STREAM_BUF_SIZE; + + result = encode_jpg(jpg_reg_ctx, param.thumb_enc_param); + } + out = copy_to_user((void *)arg, (void *) & param, sizeof(jpg_args)); + break; + + case IOCTL_JPG_GET_STRBUF: + jpg_dbg("IOCTL_JPG_GET_STRBUF\n"); + unlock_jpg_mutex(); + return arg + JPG_MAIN_STRART; + + case IOCTL_JPG_GET_THUMB_STRBUF: + jpg_dbg("IOCTL_JPG_GET_THUMB_STRBUF\n"); + unlock_jpg_mutex(); + return arg + JPG_THUMB_START; + + case IOCTL_JPG_GET_FRMBUF: + jpg_dbg("IOCTL_JPG_GET_FRMBUF\n"); + unlock_jpg_mutex(); + return arg + IMG_MAIN_START; + + case IOCTL_JPG_GET_THUMB_FRMBUF: + jpg_dbg("IOCTL_JPG_GET_THUMB_FRMBUF\n"); + unlock_jpg_mutex(); + return arg + IMG_THUMB_START; + + case IOCTL_JPG_GET_PHY_FRMBUF: + jpg_dbg("IOCTL_JPG_GET_PHY_FRMBUF\n"); + unlock_jpg_mutex(); + return jpg_data_base_addr + JPG_STREAM_BUF_SIZE + JPG_STREAM_THUMB_BUF_SIZE; + + case IOCTL_JPG_GET_PHY_THUMB_FRMBUF: + jpg_dbg("IOCTL_JPG_GET_PHY_THUMB_FRMBUF\n"); + unlock_jpg_mutex(); + return jpg_data_base_addr + JPG_STREAM_BUF_SIZE + + JPG_STREAM_THUMB_BUF_SIZE + JPG_FRAME_BUF_SIZE; + + default : + jpg_dbg("JPG Invalid ioctl : 0x%X\n", cmd); + } + + unlock_jpg_mutex(); + + return result; +} + +static unsigned int s3c_jpeg_poll(struct file *file, poll_table *wait) +{ + unsigned int mask = 0; + + jpg_dbg("enter poll \n"); + poll_wait(file, &wait_queue_jpeg, wait); + mask = POLLOUT | POLLWRNORM; + return mask; +} +int s3c_jpeg_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long max_size; + unsigned long page_frame_no; + + page_frame_no = __phys_to_pfn(jpg_data_base_addr); + + max_size = JPG_TOTAL_BUF_SIZE + PAGE_SIZE - (JPG_TOTAL_BUF_SIZE % PAGE_SIZE); + + if (size > max_size) { + return -EINVAL; + } + + vma->vm_flags |= VM_RESERVED | VM_IO; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (remap_pfn_range(vma, vma->vm_start, page_frame_no, size, \ + vma->vm_page_prot)) { + jpg_err("jpeg remap error"); + return -EAGAIN; + } + + return 0; +} + + +static const struct file_operations jpeg_fops = { + owner: THIS_MODULE, + open: s3c_jpeg_open, + release: s3c_jpeg_release, + ioctl: s3c_jpeg_ioctl, + read: s3c_jpeg_read, + write: s3c_jpeg_write, + mmap: s3c_jpeg_mmap, + poll: s3c_jpeg_poll, +}; + + +static struct miscdevice s3c_jpeg_miscdev = { + minor: 254, + name: "s3c-jpg", + fops: &jpeg_fops +}; + + +static int s3c_jpeg_probe(struct platform_device *pdev) +{ + struct resource *res; + static int size; + static int ret; + HANDLE h_mutex; + + s3c_jpeg_clk = clk_get(&pdev->dev, "jpeg"); + + if (IS_ERR(s3c_jpeg_clk)) { + jpg_err("failed to find jpeg clock source\n"); + return -ENOENT; + } + + clk_enable(s3c_jpeg_clk); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (res == NULL) { + jpg_err("failed to get memory region resouce\n"); + return -ENOENT; + } + + size = (res->end - res->start) + 1; + s3c_jpeg_mem = request_mem_region(res->start, size, pdev->name); + + if (s3c_jpeg_mem == NULL) { + jpg_err("failed to get memory region\n"); + return -ENOENT; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + + if (res == NULL) { + jpg_err("failed to get irq resource\n"); + return -ENOENT; + } + + irq_no = res->start; + ret = request_irq(res->start, (void *)s3c_jpeg_irq, 0, pdev->name, pdev); + + if (ret != 0) { + jpg_err("failed to install irq (%d)\n", ret); + return ret; + } + + s3c_jpeg_base = ioremap(s3c_jpeg_mem->start, size); + + if (s3c_jpeg_base == 0) { + jpg_err("failed to ioremap() region\n"); + return -EINVAL; + } + + init_waitqueue_head(&wait_queue_jpeg); + + jpg_dbg("JPG_Init\n"); + + // Mutex initialization + h_mutex = create_jpg_mutex(); + + if (h_mutex == NULL) { + jpg_err("JPG Mutex Initialize error\r\n"); + return FALSE; + } + + ret = lock_jpg_mutex(); + + if (!ret) { + jpg_err("JPG Mutex Lock Fail\n"); + return FALSE; + } + + instanceNo = 0; + + unlock_jpg_mutex(); + + ret = misc_register(&s3c_jpeg_miscdev); + + /* clock disable */ + clk_disable(s3c_jpeg_clk); + + return 0; +} + +static int s3c_jpeg_remove(struct platform_device *dev) +{ + if (s3c_jpeg_mem != NULL) { + release_resource(s3c_jpeg_mem); + kfree(s3c_jpeg_mem); + s3c_jpeg_mem = NULL; + } + + free_irq(irq_no, dev); + misc_deregister(&s3c_jpeg_miscdev); + return 0; +} + +#ifdef CONFIG_CPU_S5PV210 +static int s3c_jpeg_suspend(struct platform_device *pdev, pm_message_t state) +{ + int ret; + /* clock disable */ + clk_disable(s3c_jpeg_clk); + + ret = s5pv210_pd_disable("jpeg_pd"); + if (ret < 0) { + jpg_err("failed to disable jpeg power domain\n"); + return FALSE; + } + return 0; +} + +static int s3c_jpeg_resume(struct platform_device *pdev) +{ + int ret; + + ret = s5pv210_pd_enable("jpeg_pd"); + if (ret < 0) { + jpg_err("failed to enable jpeg power domain\n"); + return FALSE; + } + + /* clock enable */ + clk_enable(s3c_jpeg_clk); + + return 0; +} +#endif + +static struct platform_driver s3c_jpeg_driver = { + .probe = s3c_jpeg_probe, + .remove = s3c_jpeg_remove, + .shutdown = NULL, + .suspend = s3c_jpeg_suspend, + .resume = s3c_jpeg_resume, + .driver = { + .owner = THIS_MODULE, + .name = "s3c-jpg", + }, +}; + +static char banner[] __initdata = KERN_INFO "S3C JPEG Driver, (c) 2007 Samsung Electronics\n"; + +static int __init s3c_jpeg_init(void) +{ + printk(banner); + printk("JPEG driver for S5PV210 \n"); + return platform_driver_register(&s3c_jpeg_driver); +} + +static void __exit s3c_jpeg_exit(void) +{ + DWORD ret; + + jpg_dbg("JPG_Deinit\n"); + + ret = lock_jpg_mutex(); + + if (!ret) { + jpg_err("JPG Mutex Lock Fail\r\n"); + } + + unlock_jpg_mutex(); + + delete_jpg_mutex(); + + platform_driver_unregister(&s3c_jpeg_driver); + jpg_dbg("S3C JPEG driver module exit\n"); +} + +module_init(s3c_jpeg_init); +module_exit(s3c_jpeg_exit); + +MODULE_AUTHOR("Peter, Oh"); +MODULE_DESCRIPTION("S3C JPEG Encoder/Decoder Device Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h new file mode 100644 index 0000000..11c359e --- /dev/null +++ b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h @@ -0,0 +1,33 @@ +/* linux/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Header file for Samsung Jpeg Interface driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +#ifndef __JPEG_DRIVER_H__ +#define __JPEG_DRIVER_H__ + + +#define MAX_INSTANCE_NUM 1 +#define MAX_PROCESSING_THRESHOLD 1000 // 1Sec + +#define JPEG_IOCTL_MAGIC 'J' + +#define IOCTL_JPG_DECODE _IO(JPEG_IOCTL_MAGIC, 1) +#define IOCTL_JPG_ENCODE _IO(JPEG_IOCTL_MAGIC, 2) +#define IOCTL_JPG_GET_STRBUF _IO(JPEG_IOCTL_MAGIC, 3) +#define IOCTL_JPG_GET_FRMBUF _IO(JPEG_IOCTL_MAGIC, 4) +#define IOCTL_JPG_GET_THUMB_STRBUF _IO(JPEG_IOCTL_MAGIC, 5) +#define IOCTL_JPG_GET_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 6) +#define IOCTL_JPG_GET_PHY_FRMBUF _IO(JPEG_IOCTL_MAGIC, 7) +#define IOCTL_JPG_GET_PHY_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 8) +#define JPG_CLOCK_DIVIDER_RATIO_QUARTER 4 + +#endif /*__JPEG_DRIVER_H__*/ |