aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-07-21 23:04:45 +0200
committerDaniel Hillenbrand <daniel.hillenbrand@codeworkx.de>2012-07-21 23:04:45 +0200
commit0a1182796f6475b8cb2ff1781dad873a744b3197 (patch)
treee15b5256dac226c49a25b5e24594cd638e2fec2c /drivers/media/video
parent633018c13fe06461d9c60692fbb114734aa37802 (diff)
downloadkernel_samsung_smdk4412-0a1182796f6475b8cb2ff1781dad873a744b3197.zip
kernel_samsung_smdk4412-0a1182796f6475b8cb2ff1781dad873a744b3197.tar.gz
kernel_samsung_smdk4412-0a1182796f6475b8cb2ff1781dad873a744b3197.tar.bz2
samsung opensource update3
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/s5c73m3.c307
-rw-r--r--drivers/media/video/s5c73m3.h8
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h3
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h1
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c11
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c11
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c12
-rw-r--r--drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c57
-rw-r--r--drivers/media/video/samsung/mali/linux/mali_osk_notification.c7
-rw-r--r--drivers/media/video/samsung/mfc5x/mfc_dec.c6
-rw-r--r--drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c5
-rw-r--r--drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c4
12 files changed, 320 insertions, 112 deletions
diff --git a/drivers/media/video/s5c73m3.c b/drivers/media/video/s5c73m3.c
index ea07a34..5db5f7f 100644
--- a/drivers/media/video/s5c73m3.c
+++ b/drivers/media/video/s5c73m3.c
@@ -37,6 +37,7 @@
#endif
#include <linux/regulator/machine.h>
+#include <linux/leds-aat1290a.h>
#include <media/s5c73m3_platform.h>
#include "s5c73m3.h"
@@ -163,6 +164,8 @@ static u8 sysfs_phone_fw[10] = {0,};
static u8 sysfs_sensor_type[15] = {0,};
static u8 sysfs_isp_core[10] = {0,};
static u8 data_memory[500000] = {0,};
+static u32 crc_table[256] = {0,};
+static int copied_fw_binary;
static u16 isp_chip_info1;
static u16 isp_chip_info2;
@@ -312,6 +315,48 @@ static int s5c73m3_read(struct v4l2_subdev *sd,
return err;
}
+static int s5c73m3_i2c_check_status_with_CRC(struct v4l2_subdev *sd)
+{
+ int err = 0;
+ int index = 0;
+ u16 status = 0;
+ u16 i2c_status = 0;
+ u16 i2c_seq_status = 0;
+
+ do {
+ err = s5c73m3_read(sd, 0x0009, S5C73M3_STATUS, &status);
+ err = s5c73m3_read(sd, 0x0009,
+ S5C73M3_I2C_ERR_STATUS, &i2c_status);
+ if (i2c_status & ERROR_STATUS_CHECK_BIN_CRC) {
+ cam_dbg("failed to check CRC value of ISP Ram\n");
+ err = -1;
+ break;
+ }
+
+ if (status == 0xffff)
+ break;
+
+ index++;
+ udelay(500);
+ } while (index < 2000); /* 1 sec */
+
+ if (index >= 2000) {
+ err = s5c73m3_read(sd, 0x0009,
+ S5C73M3_I2C_ERR_STATUS, &i2c_status);
+ err = s5c73m3_read(sd, 0x0009,
+ S5C73M3_I2C_SEQ_STATUS, &i2c_seq_status);
+ cam_dbg("TimeOut!! index:%d,status:%#x,i2c_stauts:%#x,i2c_seq_status:%#x\n",
+ index,
+ status,
+ i2c_status,
+ i2c_seq_status);
+
+ err = -1;
+ }
+
+ return err;
+}
+
static int s5c73m3_i2c_check_status(struct v4l2_subdev *sd)
{
int err = 0;
@@ -346,6 +391,46 @@ static int s5c73m3_i2c_check_status(struct v4l2_subdev *sd)
return err;
}
+void s5c73m3_make_CRC_table(u32 *table, u32 id)
+{
+ u32 i, j, k;
+
+ for(i = 0; i < 256; ++i) {
+ k = i;
+ for(j = 0; j < 8; ++j) {
+ if(k & 1)
+ k = (k >> 1) ^ id;
+ else
+ k >>= 1;
+ }
+ table[i] = k;
+ }
+}
+
+static int s5c73m3_reset_module(struct v4l2_subdev *sd, bool powerReset)
+{
+ struct s5c73m3_state *state = to_state(sd);
+ int err = 0;
+
+ cam_trace("E\n");
+
+ if (powerReset) {
+ err = state->pdata->power_on_off(0);
+ CHECK_ERR(err);
+ err = state->pdata->power_on_off(1);
+ CHECK_ERR(err);
+ } else {
+ err = state->pdata->is_isp_reset();
+ CHECK_ERR(err);
+ }
+ err = s5c73m3_set_timing_register_for_vdd(sd);
+ CHECK_ERR(err);
+
+ cam_trace("X\n");
+
+ return err;
+}
+
static int s5c73m3_writeb(struct v4l2_subdev *sd,
unsigned short addr, unsigned short data)
{
@@ -487,6 +572,27 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd)
mm_segment_t old_fs;
long ret = 0;
char fw_path[25] = {0,};
+ u8 mem0 =0, mem1 = 0;
+ u32 CRC = 0;
+ u32 DataCRC = 0;
+ u32 IntOriginalCRC = 0;
+ u32 crc_index = 0;
+ int retryCnt = 2;
+
+ if (state->sensor_fw[0] == 'O') {
+ sprintf(fw_path, "/data/cfw/SlimISP_G%c.bin",
+ state->sensor_fw[1]);
+ } else if (state->sensor_fw[0] == 'S') {
+ sprintf(fw_path, "/data/cfw/SlimISP_Z%c.bin",
+ state->sensor_fw[1]);
+ } else {
+ sprintf(fw_path, "/data/cfw/SlimISP_%c%c.bin",
+ state->sensor_fw[0],
+ state->sensor_fw[1]);
+ }
+
+ /* Make CRC Table */
+ s5c73m3_make_CRC_table((u32 *)&crc_table, 0xEDB88320);
/*ARM go*/
err = s5c73m3_write(sd, 0x3000, 0x0004, 0xFFFF);
@@ -554,32 +660,18 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd)
mdelay(200);
- old_fs = get_fs();
- set_fs(KERNEL_DS);
-
- if (state->sensor_fw[0] == 'O') {
- sprintf(fw_path, "/data/cfw/SlimISP_G%c.bin",
- state->sensor_fw[1]);
- } else if (state->sensor_fw[0] == 'S') {
- sprintf(fw_path, "/data/cfw/SlimISP_Z%c.bin",
- state->sensor_fw[1]);
- } else {
- sprintf(fw_path, "/data/cfw/SlimISP_%c%c.bin",
- state->sensor_fw[0],
- state->sensor_fw[1]);
- }
-
- fp = filp_open(fw_path, O_WRONLY|O_CREAT, 0644);
- if (IS_ERR(fp) || fp == NULL) {
- cam_err("failed to open %s, err %ld\n",
- fw_path, PTR_ERR(fp));
- err = -EINVAL;
- goto out;
- }
+retry:
+ memset(data_memory, 0, sizeof(data_memory));
+ mem0 =0, mem1 = 0;
+ CRC = 0;
+ DataCRC = 0;
+ IntOriginalCRC = 0;
+ crc_index = 0;
/* SPI Copy mode ready I2C CMD */
err = s5c73m3_writeb(sd, 0x0924, 0x0000);
CHECK_ERR(err);
+ cam_dbg("sent SPI ready CMD\n");
rxSize = 64*1024;
mdelay(10);
@@ -589,19 +681,72 @@ static int s5c73m3_get_sensor_fw_binary(struct v4l2_subdev *sd)
state->sensor_size, rxSize);
CHECK_ERR(err);
- ret = vfs_write(fp, (char __user *)data_memory,
- state->sensor_size, &fp->f_pos);
+ CRC = ~CRC;
+ for(crc_index = 0;crc_index < (state->sensor_size-4)/2;crc_index++) {
+ /*low byte*/
+ mem0 = (unsigned char)(data_memory[crc_index*2] & 0x00ff);
+ /*high byte*/
+ mem1 = (unsigned char)(data_memory[crc_index*2+1] & 0x00ff);
+ CRC = crc_table[(CRC ^ (mem0)) & 0xFF] ^ (CRC >> 8);
+ CRC = crc_table[(CRC ^ (mem1)) & 0xFF] ^ (CRC >> 8);
+ }
+ CRC = ~CRC;
+
+ DataCRC = (CRC&0x000000ff)<<24;
+ DataCRC += (CRC&0x0000ff00)<<8;
+ DataCRC += (CRC&0x00ff0000)>>8;
+ DataCRC += (CRC&0xff000000)>>24;
+ cam_err("made CSC value by S/W = 0x%x\n", DataCRC);
+
+ IntOriginalCRC = (data_memory[state->sensor_size-4]&0x00ff)<<24;
+ IntOriginalCRC += (data_memory[state->sensor_size-3]&0x00ff)<<16;
+ IntOriginalCRC += (data_memory[state->sensor_size-2]&0x00ff)<<8;
+ IntOriginalCRC += (data_memory[state->sensor_size-1]&0x00ff);
+ cam_err("Original CRC Int = 0x%x\n", IntOriginalCRC);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ if (IntOriginalCRC == DataCRC) {
+ fp = filp_open(fw_path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (IS_ERR(fp) || fp == NULL) {
+ cam_err("failed to open %s, err %ld\n",
+ fw_path, PTR_ERR(fp));
+ err = -EINVAL;
+ goto out;
+ }
+
+ ret = vfs_write(fp, (char __user *)data_memory,
+ state->sensor_size, &fp->f_pos);
+
+ if (camfw_info[S5C73M3_SD_CARD].opened == 0) {
+ memcpy(state->phone_fw,
+ state->sensor_fw,
+ S5C73M3_FW_VER_LEN);
+ state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' ';
+
+ memcpy(sysfs_phone_fw,
+ state->phone_fw,
+ sizeof(state->phone_fw));
+ cam_dbg("Changed to Phone_version = %s\n",
+ state->phone_fw);
+ }
+ } else {
+ if (retryCnt > 0) {
+ set_fs(old_fs);
+ retryCnt--;
+ goto retry;
+ }
+ }
if (fp != NULL)
filp_close(fp, current->files);
out:
set_fs(old_fs);
-
return err;
}
-
static int s5c73m3_get_sensor_fw_version(struct v4l2_subdev *sd)
{
struct s5c73m3_state *state = to_state(sd);
@@ -802,7 +947,6 @@ static int s5c73m3_get_phone_fw_version(struct v4l2_subdev *sd)
int err = 0;
int retVal = 0;
int fw_requested = 1;
- int copied_fw_binary = 0;
if (state->sensor_fw[0] == 'O') {
sprintf(fw_path, "SlimISP_G%c.bin",
@@ -885,14 +1029,12 @@ request_fw:
state->fw_index = S5C73M3_IN_DATA;
}
} else {
- cam_dbg("get new fw to F-ROM : %s Version\n",
+ cam_dbg("can't open %s Ver. Firmware. so, download from F-ROM\n",
state->sensor_fw);
if (fw != NULL)
release_firmware(fw);
- retVal = state->pdata->is_isp_reset();
- CHECK_ERR(retVal);
- retVal = s5c73m3_set_timing_register_for_vdd(sd);
+ retVal = s5c73m3_reset_module(sd, true);
CHECK_ERR(retVal);
retVal = s5c73m3_get_sensor_fw_binary(sd);
CHECK_ERR(retVal);
@@ -901,17 +1043,13 @@ request_fw:
}
}
- if (copied_fw_binary) {
+ if (!copied_fw_binary) {
memcpy(state->phone_fw,
- state->sensor_fw,
+ camfw_info[state->fw_index].ver,
S5C73M3_FW_VER_LEN);
state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' ';
- } else {
- memcpy(state->phone_fw,
- camfw_info[state->fw_index].ver,
- S5C73M3_FW_VER_LEN);
- state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' ';
}
+
memcpy(sysfs_phone_fw,
state->phone_fw,
sizeof(state->phone_fw));
@@ -1049,10 +1187,11 @@ static int s5c73m3_check_fw_date(struct v4l2_subdev *sd)
static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download)
{
- struct s5c73m3_state *state = to_state(sd);
int err, i;
int retVal;
+ copied_fw_binary = 0;
+
if (!download) {
for (i = 0; i < S5C73M3_PATH_MAX; i++)
camfw_info[i].opened = 0;
@@ -1065,16 +1204,22 @@ static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download)
}
retVal = s5c73m3_check_fw_date(sd);
- err = state->pdata->is_isp_reset();
- CHECK_ERR(err);
- err = s5c73m3_set_timing_register_for_vdd(sd);
- CHECK_ERR(err);
/* retVal = 0 : Same Version
- retVal < 0 : Phone Version is latest Version than sensorFW.
- retVal > 0 : Sensor Version is latest version than phoenFW. */
- if (retVal <= 0 || download) {
+ retVal < 0 : Phone Version is latest Version than sensorFW.
+ retVal > 0 : Sensor Version is latest version than phoenFW. */
+ if (retVal <= 0||download) {
cam_dbg("Loading From PhoneFW......\n");
+
+ /* In case that there is no FW in phone and FW needs to be
+ downloaded from F-ROM, ISP power reset is required before
+ loading FW to ISP for F-ROM to work properly.*/
+ if (copied_fw_binary)
+ err = s5c73m3_reset_module(sd, true);
+ else
+ err = s5c73m3_reset_module(sd, false);
+ CHECK_ERR(err);
+
err = s5c73m3_SPI_booting(sd);
CHECK_ERR(err);
@@ -1084,26 +1229,13 @@ static int s5c73m3_check_fw(struct v4l2_subdev *sd, int download)
}
} else {
cam_dbg("Loading From SensorFW......\n");
-#if 0
- err = s5c73m3_SPI_booting_by_ISP(sd);
+ err = s5c73m3_reset_module(sd, true);
CHECK_ERR(err);
-#else
err = s5c73m3_get_sensor_fw_binary(sd);
CHECK_ERR(err);
-
- memcpy(state->phone_fw,
- state->sensor_fw,
- S5C73M3_FW_VER_LEN);
- state->phone_fw[S5C73M3_FW_VER_LEN+1] = ' ';
-
- memcpy(sysfs_phone_fw,
- state->phone_fw,
- sizeof(state->phone_fw));
- cam_dbg("Changed to Phone_version = %s\n",
- state->phone_fw);
-#endif
}
+
return 0;
}
@@ -1927,6 +2059,27 @@ static int s5c73m3_aeawb_lock_unlock(struct v4l2_subdev *sd, int val)
return 0;
}
+static void s5c73m3_wait_for_preflash_fire(struct v4l2_subdev *sd)
+{
+ u16 pre_flash = false;
+ u16 timeout_cnt = 0;
+
+ do {
+ s5c73m3_read(sd, 0x0009,
+ S5C73M3_STILL_PRE_FLASH | 0x5000, &pre_flash);
+ if (pre_flash || timeout_cnt > 20) {
+ if (!pre_flash) {
+ cam_dbg("pre_Flash = %d, timeout_cnt = %d\n",
+ pre_flash, timeout_cnt);
+ }
+ break;
+ } else
+ timeout_cnt++;
+
+ mdelay(15);
+ } while (1);
+}
+
static int s5c73m3_start_capture(struct v4l2_subdev *sd, int val)
{
struct s5c73m3_state *state = to_state(sd);
@@ -1940,7 +2093,7 @@ static int s5c73m3_start_capture(struct v4l2_subdev *sd, int val)
if (!pre_flash) {
err = s5c73m3_writeb(sd, S5C73M3_STILL_PRE_FLASH
, S5C73M3_STILL_PRE_FLASH_FIRE);
- msleep(100);
+ s5c73m3_wait_for_preflash_fire(sd);
}
err = s5c73m3_writeb(sd, S5C73M3_STILL_MAIN_FLASH
, S5C73M3_STILL_MAIN_FLASH_FIRE);
@@ -1954,7 +2107,7 @@ static int s5c73m3_start_capture(struct v4l2_subdev *sd, int val)
if (isneed_flash) {
err = s5c73m3_writeb(sd, S5C73M3_STILL_PRE_FLASH
, S5C73M3_STILL_PRE_FLASH_FIRE);
- msleep(100);
+ s5c73m3_wait_for_preflash_fire(sd);
err = s5c73m3_writeb(sd,
S5C73M3_STILL_MAIN_FLASH,
S5C73M3_STILL_MAIN_FLASH_FIRE);
@@ -3109,7 +3262,7 @@ static int s5c73m3_read_vdd_core(struct v4l2_subdev *sd)
set_fs(KERNEL_DS);
fp = filp_open(S5C73M3_CORE_VDD,
- O_WRONLY|O_CREAT, 0666);
+ O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (IS_ERR(fp))
goto out;
@@ -3197,34 +3350,31 @@ static int s5c73m3_init(struct v4l2_subdev *sd, u32 val)
#endif
CHECK_ERR(err);
- err = s5c73m3_i2c_check_status(sd);
+ err = s5c73m3_i2c_check_status_with_CRC(sd);
if (err < 0) {
cam_err("ISP is not ready. retry loading fw!!\n");
/* retry */
retVal = s5c73m3_check_fw_date(sd);
- err = state->pdata->is_isp_reset();
- CHECK_ERR(err);
- err = s5c73m3_set_timing_register_for_vdd(sd);
- CHECK_ERR(err);
-
/* retVal = 0 : Same Version
retVal < 0 : Phone Version is latest Version than sensorFW.
retVal > 0 : Sensor Version is latest version than phoenFW. */
if (retVal <= 0) {
cam_dbg("Loading From PhoneFW......\n");
+ err = s5c73m3_reset_module(sd, false);
+ CHECK_ERR(err);
err = s5c73m3_SPI_booting(sd);
CHECK_ERR(err);
} else {
cam_dbg("Loading From SensorFW......\n");
+ err = s5c73m3_reset_module(sd, true);
+ CHECK_ERR(err);
err = s5c73m3_get_sensor_fw_binary(sd);
CHECK_ERR(err);
}
-
}
state->isp.bad_fw = 0;
-
s5c73m3_init_param(sd);
return 0;
@@ -3271,18 +3421,7 @@ static ssize_t s5c73m3_camera_rear_flash(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- int err;
-
- if (buf[0] == '0')
- err = s5c73m3_writeb(sd_internal, S5C73M3_FLASH_TORCH,
- S5C73M3_FLASH_TORCH_OFF);
- else
- err = s5c73m3_writeb(sd_internal, S5C73M3_FLASH_TORCH,
- S5C73M3_FLASH_TORCH_ON);
-
- CHECK_ERR(err);
-
- return count;
+ return aat1290a_power(dev, attr, buf, count);
}
static ssize_t s5c73m3_camera_isp_core_show(struct device *dev,
diff --git a/drivers/media/video/s5c73m3.h b/drivers/media/video/s5c73m3.h
index 97a697b..40d7eaf 100644
--- a/drivers/media/video/s5c73m3.h
+++ b/drivers/media/video/s5c73m3.h
@@ -450,10 +450,10 @@ struct s5c73m3_state {
#define ERR_STATUS_FROM_INIT (1<<0x4)
#define ERR_STATUS_I2C_CIS_STREAM_OFF (1<<0x5)
#define ERR_STATUS_I2C_N_CMD_OVER (1<<0x6)
-#define ERR_STATUS_I2C_N_CMD_MISMATCH0 (1<<0x7)
-#define ERR_STATUS_I2C_N_CMD_MISMATCH1 (1<<0x8)
-#define ERR_STATUS_EXCEPTION (1<<0x9)
-
+#define ERROR_STATUS_I2C_N_CMD_MISMATCH (1<<0x7)
+#define ERROR_STATUS_CHECK_BIN_CRC (1<<0x8)
+#define ERROR_STATUS_EXCEPTION (1<<0x9)
+#define ERROR_STATUS_INIF_INIT_STATE (0x8)
#ifdef CONFIG_VIDEO_S5C73M3_SPI
extern int s5c73m3_spi_write(const u8 *addr, const int len, const int txSize);
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h
index 97fc4cb..2d8f3b7 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d.h
@@ -40,6 +40,7 @@
#define FIMG2D_BITBLT_BLIT _IOWR(FIMG2D_IOCTL_MAGIC, 0, struct fimg2d_blit)
#define FIMG2D_BITBLT_SYNC _IOW(FIMG2D_IOCTL_MAGIC, 1, int)
#define FIMG2D_BITBLT_VERSION _IOR(FIMG2D_IOCTL_MAGIC, 2, struct fimg2d_version)
+#define FIMG2D_BITBLT_SECURE _IOW(FIMG2D_IOCTL_MAGIC, 3, unsigned int)
struct fimg2d_version {
unsigned int hw;
@@ -483,8 +484,8 @@ struct fimg2d_control {
struct resource *mem;
void __iomem *regs;
- bool err;
int irq;
+ unsigned int secure;
atomic_t nctx;
atomic_t busy;
atomic_t active;
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h
index 9165d6f..4bf8f74 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x.h
@@ -172,6 +172,7 @@ struct fimg2d_blend_coeff {
enum fimg2d_coeff d_coeff;
};
+void fimg2d4x_sw_reset(struct fimg2d_control *info);
void fimg2d4x_reset(struct fimg2d_control *info);
void fimg2d4x_enable_irq(struct fimg2d_control *info);
void fimg2d4x_disable_irq(struct fimg2d_control *info);
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c
index 9a4f8ad..fc6016c 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_blt.c
@@ -38,7 +38,9 @@ static inline void fimg2d4x_blit_wait(struct fimg2d_control *info, struct fimg2d
fimg2d_dump_command(cmd);
if (!fimg2d4x_blit_done_status(info))
- info->err = true; /* device error */
+ printk(KERN_ERR "[%s] G2D operation is not finished", __func__);
+
+ fimg2d4x_sw_reset(info);
}
}
@@ -63,19 +65,16 @@ void fimg2d4x_bitblt(struct fimg2d_control *info)
fimg2d_clk_on(info);
while (1) {
+ spin_lock(&info->bltlock);
cmd = fimg2d_get_first_command(info);
if (!cmd) {
- spin_lock(&info->bltlock);
atomic_set(&info->active, 0);
spin_unlock(&info->bltlock);
break;
}
+ spin_unlock(&info->bltlock);
ctx = cmd->ctx;
- if (info->err) {
- printk(KERN_ERR "[%s] device error\n", __func__);
- goto blitend;
- }
atomic_set(&info->busy, 1);
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c
index 8135ecd..4eb4d04 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d4x_hw.c
@@ -28,6 +28,17 @@ static const int msk_oprmode = (int)MSK_ARGB;
static const int premult_round_mode = (int)PREMULT_ROUND_1; /* (A+1)*B) >> 8 */
static const int blend_round_mode = (int)BLEND_ROUND_0; /* (A+1)*B) >> 8 */
+void fimg2d4x_sw_reset(struct fimg2d_control *info)
+{
+ wr(FIMG2D_SOFT_RESET, FIMG2D_SOFT_RESET_REG);
+ /* turn off wince option */
+ wr(0x0, FIMG2D_BLEND_FUNCTION_REG);
+
+ /* set default repeat mode to reflect(mirror) */
+ wr(FIMG2D_SRC_REPEAT_REFLECT, FIMG2D_SRC_REPEAT_MODE_REG);
+ wr(FIMG2D_MSK_REPEAT_REFLECT, FIMG2D_MSK_REPEAT_MODE_REG);
+}
+
void fimg2d4x_reset(struct fimg2d_control *info)
{
#ifdef SOFT_RESET_ENABLED
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
index 26ea56b..eaa722c 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_ctx.c
@@ -295,16 +295,20 @@ int fimg2d_add_command(struct fimg2d_control *info, struct fimg2d_context *ctx,
if (copy_from_user(&cmd->image[i], buf[i],
sizeof(struct fimg2d_image))) {
if ((blit->dst) && (type == ADDR_USER))
- if (!down_write_trylock(&page_alloc_slow_rwsem))
- return -EAGAIN;
+ if (!down_write_trylock(&page_alloc_slow_rwsem)) {
+ ret = -EAGAIN;
+ goto err_user;
+ }
ret = -EFAULT;
goto err_user;
}
}
if ((blit->dst) && (type == ADDR_USER))
- if (!down_write_trylock(&page_alloc_slow_rwsem))
- return -EAGAIN;
+ if (!down_write_trylock(&page_alloc_slow_rwsem)) {
+ ret = -EAGAIN;
+ goto err_user;
+ }
cmd->ctx = ctx;
cmd->op = blit->op;
diff --git a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c
index 6ae4d6e..ed14901 100644
--- a/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c
+++ b/drivers/media/video/samsung/fimg2d4x-exynos4/fimg2d_drv.c
@@ -38,8 +38,14 @@
#include "fimg2d_clk.h"
#include "fimg2d_ctx.h"
#include "fimg2d_helper.h"
+#include "fimg2d_cache.h"
#define CTX_TIMEOUT msecs_to_jiffies(1000)
+#define LV1_SHIFT 20
+#define LV2_BASE_MASK 0x3ff
+#define LV2_PT_MASK 0xff000
+#define LV2_SHIFT 12
+#define LV1_DESC_MASK 0x3
static struct fimg2d_control *info;
@@ -58,7 +64,13 @@ static DECLARE_WORK(fimg2d_work, fimg2d_worker);
static irqreturn_t fimg2d_irq(int irq, void *dev_id)
{
fimg2d_debug("irq\n");
- info->stop(info);
+ if (!atomic_read(&info->clkon)) {
+ fimg2d_clk_on(info);
+ info->stop(info);
+ fimg2d_clk_off(info);
+ } else {
+ info->stop(info);
+ }
return IRQ_HANDLED;
}
@@ -67,6 +79,8 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
unsigned long pgtable_base, unsigned long fault_addr)
{
struct fimg2d_bltcmd *cmd;
+ unsigned long *pgd;
+ unsigned long *lv1d, *lv2d;
if (itype == SYSMMU_PAGEFAULT) {
printk(KERN_ERR "[%s] sysmmu page fault(0x%lx), pgd(0x%lx)\n",
@@ -91,11 +105,20 @@ static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
fimg2d_dump_command(cmd);
+ pgd = (unsigned long *)cmd->ctx->mm->pgd;
+ lv1d = pgd + (fault_addr >> LV1_SHIFT);
+ printk(KERN_ERR " Level 1 descriptor(0x%lx)\n", *lv1d);
+ if ((*lv1d & LV1_DESC_MASK) != 0x1) {
+ fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4);
+ goto next;
+ }
+
+ lv2d = (unsigned long *)phys_to_virt(*lv1d & ~LV2_BASE_MASK) +
+ ((fault_addr & LV2_PT_MASK) >> LV2_SHIFT);
+ printk(KERN_ERR " Level 2 descriptor(0x%lx)\n", *lv2d);
+ fimg2d_clean_outer_pagetable(cmd->ctx->mm, fault_addr, 4);
next:
- fimg2d_clk_dump(info);
- info->dump(info);
- BUG();
return 0;
}
@@ -106,8 +129,6 @@ static void fimg2d_context_wait(struct fimg2d_context *ctx)
atomic_set(&info->active, 1);
queue_work(info->work_q, &fimg2d_work);
printk(KERN_ERR "[%s] ctx %p cmd wait timeout\n", __func__, ctx);
- if (info->err)
- break;
}
}
}
@@ -188,11 +209,8 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case FIMG2D_BITBLT_BLIT:
- if (info->err) {
- printk(KERN_ERR "[%s] device error, do sw fallback\n",
- __func__);
+ if (info->secure)
return -EFAULT;
- }
if (copy_from_user(&blit, (void *)arg, sizeof(blit)))
return -EFAULT;
@@ -245,6 +263,24 @@ static long fimg2d_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EFAULT;
break;
+ case FIMG2D_BITBLT_SECURE:
+ if (copy_from_user(&info->secure,
+ (unsigned int *)arg,
+ sizeof(unsigned int))) {
+ printk(KERN_ERR
+ "[%s] failed to FIMG2D_BITBLT_SECURE: copy_from_user error\n\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ while (1) {
+ if (fimg2d_queue_is_empty(&info->cmd_q))
+ break;
+ mdelay(2);
+ }
+
+ break;
+
default:
printk(KERN_ERR "[%s] unknown ioctl\n", __func__);
ret = -EFAULT;
@@ -278,6 +314,7 @@ static int fimg2d_setup_controller(struct fimg2d_control *info)
atomic_set(&info->busy, 0);
atomic_set(&info->nctx, 0);
atomic_set(&info->active, 0);
+ info->secure = 0;
spin_lock_init(&info->bltlock);
diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c
index 74a18e8..eef839f 100644
--- a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c
+++ b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c
@@ -15,6 +15,8 @@
#include "mali_osk.h"
#include "mali_kernel_common.h"
+#include "mali_pmm.h"
+#include "mali_pmm_state.h"
/* needed to detect kernel version specific code */
#include <linux/version.h>
@@ -65,6 +67,11 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size )
/* OPT Recycling of notification objects */
_mali_osk_notification_wrapper_t *notification;
+ if (MALI_PMM_NOTIFICATION_TYPE == type) {
+ if (size != sizeof(mali_pmm_message_t))
+ return NULL;
+ }
+
notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, GFP_KERNEL );
if (NULL == notification)
{
diff --git a/drivers/media/video/samsung/mfc5x/mfc_dec.c b/drivers/media/video/samsung/mfc5x/mfc_dec.c
index 6e0645d..fd78b7d 100644
--- a/drivers/media/video/samsung/mfc5x/mfc_dec.c
+++ b/drivers/media/video/samsung/mfc5x/mfc_dec.c
@@ -2388,6 +2388,12 @@ int mfc_exec_decoding(struct mfc_inst_ctx *ctx, union mfc_args *args)
offset = CheckMPEG4StartCode(stream_vir+consumed,
dec_ctx->streamsize - consumed);
+
+ if (offset == -1) {
+ mfc_warn("No start code in remained bitstream: %d\n", offset);
+ return ret;
+ }
+
if (offset > 4)
consumed += offset;
diff --git a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
index 7af8a15..68508e7 100644
--- a/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
+++ b/drivers/media/video/samsung/tvout/s5p_tvout_v4l2.c
@@ -953,8 +953,11 @@ static int s5p_tvout_tvif_release(struct file *file)
tvout_dbg("on_stop_process(%d)\n", on_stop_process);
atomic_dec(&s5p_tvout_v4l2_private.tvif_use);
- if (atomic_read(&s5p_tvout_v4l2_private.tvif_use) == 0)
+ if (atomic_read(&s5p_tvout_v4l2_private.tvif_use) == 0) {
+ s5p_tvout_mutex_lock();
s5p_tvif_ctrl_stop();
+ s5p_tvout_mutex_unlock();
+ }
on_stop_process = false;
tvout_dbg("on_stop_process(%d)\n", on_stop_process);
diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c
index 323c13c..07fbd3f 100644
--- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c
+++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c
@@ -142,10 +142,10 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor)
if (is_cached)
{
- new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN );
+ new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN );
} else
{
- new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD);
+ new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | __GFP_COLD);
}
if (NULL == new_page)
{